511 lines
18 KiB
C
511 lines
18 KiB
C
// Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
|
|
// See LICENSE.md for license information.
|
|
// SPDX-License-Identifier: MIT
|
|
//
|
|
// indexedHost.c - Host-cc harness for jlSurfacePasteIndexed and
|
|
// jlSurfaceSnapIndexed (src/core/surface.c clipping, the port's rectangle
|
|
// writer and reader behind it). Each case is checked against a reference
|
|
// built one pixel at a time with jlDrawPixel and jlSamplePixel:
|
|
// paste the surface after a paste equals a copy of the same background
|
|
// with every on-surface pixel of the rectangle plotted by hand
|
|
// (high nibbles in the source ignored, doubleWide pairs, a
|
|
// doubleWide byte cut by the left or right edge showing its one
|
|
// on-surface pixel)
|
|
// snap every byte of the rectangle equals jlSamplePixel of its column
|
|
// (0 off the surface), and the bytes between w and the stride are
|
|
// left alone
|
|
// Edge cases (odd columns, both edges, rows past both ends, w 65535, the
|
|
// int16_t limits) run first, then seeded random rectangles.
|
|
//
|
|
// The planar ports' paste and snap (src/m68k/planarIndexed.c, plain C) run
|
|
// here too, on host buffers in both of their layouts -- four separate
|
|
// planes (Amiga, X68000) and the ST's interleaved plane words -- given
|
|
// on-surface rectangles as the core hands them over, and checked against
|
|
// the same kind of pixel-by-pixel reference.
|
|
//
|
|
// Built by scripts/check-indexed.sh with -DJOEYLIB_PLATFORM_BLANK.
|
|
|
|
#include <stdbool.h>
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#include "joey/joey.h"
|
|
#include "surfaceInternal.h"
|
|
|
|
#define SRC_BYTES 81920u
|
|
#define RANDOM_CASES 600u
|
|
#define RANDOM_SEED 0x1D2C3B4Au
|
|
#define RANDOM_X_SPAN 700
|
|
#define RANDOM_X_LOW (-360)
|
|
#define RANDOM_Y_SPAN 440
|
|
#define RANDOM_Y_LOW (-220)
|
|
#define RANDOM_W_MAX 200u
|
|
#define RANDOM_H_MAX 220u
|
|
#define RANDOM_PAD_MAX 5u
|
|
#define CANARY 0xA5u
|
|
#define BACK_X_MUL 7
|
|
#define BACK_Y_MUL 3
|
|
#define PLANAR_PLANES 4u
|
|
#define PLANAR_ROW_BYTES (JL_SURFACE_WIDTH / 8)
|
|
#define PLANAR_CASES 500u
|
|
#define PLANAR_H_MAX 24u
|
|
#define ST_ROW_BYTES 160u
|
|
#define ST_GROUP_BYTES 8u
|
|
|
|
typedef struct LayoutT {
|
|
const char *name;
|
|
uint8_t *planes[PLANAR_PLANES];
|
|
uint16_t rowBytes;
|
|
uint16_t pairStep;
|
|
} LayoutT;
|
|
|
|
typedef struct CaseT {
|
|
int16_t x;
|
|
int16_t y;
|
|
uint16_t w;
|
|
uint16_t h;
|
|
uint16_t pad;
|
|
bool doubleWide;
|
|
} CaseT;
|
|
|
|
static const CaseT kEdgeCases[] = {
|
|
{ 0, 0, 160u, 200u, 0u, true },
|
|
{ 0, 0, 320u, 200u, 0u, false },
|
|
{ 1, 3, 17u, 5u, 2u, false },
|
|
{ 1, 3, 16u, 5u, 0u, false },
|
|
{ 1, 3, 17u, 5u, 1u, true },
|
|
{ -1, 10, 20u, 4u, 0u, true },
|
|
{ -1, 10, 20u, 4u, 3u, false },
|
|
{ -2, 10, 20u, 4u, 0u, true },
|
|
{ -3, 10, 2u, 4u, 0u, true },
|
|
{ -3, 10, 1u, 4u, 0u, true },
|
|
{ 319, 50, 8u, 3u, 0u, true },
|
|
{ 318, 50, 8u, 3u, 0u, true },
|
|
{ 317, 50, 8u, 3u, 0u, true },
|
|
{ 319, 50, 8u, 3u, 0u, false },
|
|
{ 320, 50, 8u, 3u, 0u, true },
|
|
{ -9, -5, 170u, 210u, 4u, true },
|
|
{ -9, -5, 340u, 210u, 4u, false },
|
|
{ 40, 198, 10u, 10u, 0u, false },
|
|
{ 40, -10, 10u, 10u, 0u, true },
|
|
{ 40, -11, 10u, 10u, 0u, true },
|
|
{ 40, 200, 10u, 10u, 0u, true },
|
|
{ 5, 5, 0u, 10u, 2u, true },
|
|
{ 5, 5, 10u, 0u, 0u, true },
|
|
{ -301, 7, 65535u, 1u, 0u, true },
|
|
{ -301, 7, 65535u, 1u, 0u, false },
|
|
{-32768, -32768, 9u, 2u, 0u, true },
|
|
{ 32767, 32767, 9u, 2u, 0u, false }
|
|
};
|
|
|
|
#define EDGE_CASE_COUNT ((uint16_t)(sizeof(kEdgeCases) / sizeof(kEdgeCases[0])))
|
|
|
|
static uint8_t gSrc[SRC_BYTES];
|
|
static uint8_t gSnap[SRC_BYTES];
|
|
static uint32_t gRandom = RANDOM_SEED;
|
|
static uint8_t gSeparate[PLANAR_PLANES][PLANAR_ROW_BYTES * JL_SURFACE_HEIGHT];
|
|
static uint8_t gInterleaved[ST_ROW_BYTES * JL_SURFACE_HEIGHT];
|
|
static uint8_t gPlanarBack[PLANAR_PLANES][ST_ROW_BYTES * JL_SURFACE_HEIGHT];
|
|
static uint8_t gRef[JL_SURFACE_HEIGHT][JL_SURFACE_WIDTH];
|
|
|
|
static bool check(const char *name, bool ok, const char *detail);
|
|
static bool comparePaste(const jlSurfaceT *got, const jlSurfaceT *want, const CaseT *c, char *detail, size_t size);
|
|
static bool compareSnap(const jlSurfaceT *back, const CaseT *c, char *detail, size_t size);
|
|
static void fillBackground(jlSurfaceT *s);
|
|
static uint32_t nextRandom(void);
|
|
static void pasteReference(jlSurfaceT *s, const CaseT *c, uint16_t stride);
|
|
static uint8_t planarGet(const LayoutT *l, uint16_t x, uint16_t y);
|
|
static uint8_t *planarByte(const LayoutT *l, uint16_t p, uint16_t x, uint16_t y);
|
|
static bool planarCase(LayoutT *l, const CaseT *c, char *detail, size_t size);
|
|
static void planarSet(const LayoutT *l, uint16_t x, uint16_t y, uint8_t color);
|
|
static void planarStore(const LayoutT *l, bool save);
|
|
static bool runCase(jlSurfaceT *stage, jlSurfaceT *ref, const jlSurfaceT *back, const CaseT *c, char *detail, size_t size);
|
|
static bool runCases(jlSurfaceT *stage, jlSurfaceT *ref, const jlSurfaceT *back, bool random);
|
|
static bool runPlanar(LayoutT *l);
|
|
static uint8_t sampleWide(const jlSurfaceT *s, int32_t x, int32_t y);
|
|
|
|
|
|
static bool check(const char *name, bool ok, const char *detail) {
|
|
printf(" %s: %s%s%s\n", name, ok ? "PASS" : "FAIL", detail[0] != '\0' ? " -- " : "", detail);
|
|
return ok;
|
|
}
|
|
|
|
|
|
static bool comparePaste(const jlSurfaceT *got, const jlSurfaceT *want, const CaseT *c, char *detail, size_t size) {
|
|
int16_t x;
|
|
int16_t y;
|
|
uint8_t a;
|
|
uint8_t b;
|
|
|
|
if (jlSurfaceHash(got) == jlSurfaceHash(want)) {
|
|
return true;
|
|
}
|
|
for (y = 0; y < JL_SURFACE_HEIGHT; y++) {
|
|
for (x = 0; x < JL_SURFACE_WIDTH; x++) {
|
|
a = jlSamplePixel(got, x, y);
|
|
b = jlSamplePixel(want, x, y);
|
|
if (a != b) {
|
|
snprintf(detail, size, "paste at (%d,%d) w %u h %u%s: pixel (%d,%d) is %u, want %u", c->x, c->y, c->w, c->h, c->doubleWide ? " doubleWide" : "", x, y, a, b);
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
snprintf(detail, size, "paste at (%d,%d) w %u h %u: hashes differ, pixels equal", c->x, c->y, c->w, c->h);
|
|
return false;
|
|
}
|
|
|
|
|
|
static bool compareSnap(const jlSurfaceT *back, const CaseT *c, char *detail, size_t size) {
|
|
const uint8_t *row;
|
|
uint32_t stride;
|
|
uint32_t r;
|
|
uint32_t i;
|
|
uint8_t want;
|
|
|
|
stride = (uint32_t)c->w + c->pad;
|
|
for (r = 0; r < c->h; r++) {
|
|
row = gSnap + r * stride;
|
|
for (i = 0; i < c->w; i++) {
|
|
want = sampleWide(back, (int32_t)c->x + (int32_t)(i << (c->doubleWide ? 1u : 0u)), (int32_t)c->y + (int32_t)r);
|
|
if (row[i] != want) {
|
|
snprintf(detail, size, "snap at (%d,%d) w %u h %u%s: byte %lu of row %lu is %u, want %u", c->x, c->y, c->w, c->h, c->doubleWide ? " doubleWide" : "", (unsigned long)i, (unsigned long)r, row[i], want);
|
|
return false;
|
|
}
|
|
}
|
|
for (; i < stride; i++) {
|
|
if (row[i] != CANARY) {
|
|
snprintf(detail, size, "snap at (%d,%d) w %u h %u: wrote past w at byte %lu of row %lu", c->x, c->y, c->w, c->h, (unsigned long)i, (unsigned long)r);
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
static void fillBackground(jlSurfaceT *s) {
|
|
int16_t x;
|
|
int16_t y;
|
|
|
|
for (y = 0; y < JL_SURFACE_HEIGHT; y++) {
|
|
for (x = 0; x < JL_SURFACE_WIDTH; x++) {
|
|
jlDrawPixel(s, x, y, (uint8_t)((x * BACK_X_MUL + y * BACK_Y_MUL) & 0x0F));
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
static uint32_t nextRandom(void) {
|
|
gRandom ^= gRandom << 13;
|
|
gRandom ^= gRandom >> 17;
|
|
gRandom ^= gRandom << 5;
|
|
return gRandom;
|
|
}
|
|
|
|
|
|
static void pasteReference(jlSurfaceT *s, const CaseT *c, uint16_t stride) {
|
|
uint32_t r;
|
|
uint32_t i;
|
|
uint32_t k;
|
|
uint32_t span;
|
|
int32_t px;
|
|
int32_t py;
|
|
uint8_t color;
|
|
|
|
span = c->doubleWide ? 2u : 1u;
|
|
for (r = 0; r < c->h; r++) {
|
|
py = (int32_t)c->y + (int32_t)r;
|
|
if (py < 0 || py >= JL_SURFACE_HEIGHT) {
|
|
continue;
|
|
}
|
|
for (i = 0; i < c->w; i++) {
|
|
color = (uint8_t)(gSrc[r * stride + i] & 0x0Fu);
|
|
for (k = 0; k < span; k++) {
|
|
px = (int32_t)c->x + (int32_t)(i * span + k);
|
|
if (px >= 0 && px < JL_SURFACE_WIDTH) {
|
|
jlDrawPixel(s, (int16_t)px, (int16_t)py, color);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
static uint8_t planarGet(const LayoutT *l, uint16_t x, uint16_t y) {
|
|
uint16_t p;
|
|
uint8_t bit;
|
|
uint8_t color;
|
|
|
|
bit = (uint8_t)(0x80u >> (x & 7u));
|
|
color = 0u;
|
|
for (p = 0; p < PLANAR_PLANES; p++) {
|
|
if ((*planarByte(l, p, x, y) & bit) != 0u) {
|
|
color = (uint8_t)(color | (1u << p));
|
|
}
|
|
}
|
|
return color;
|
|
}
|
|
|
|
|
|
static uint8_t *planarByte(const LayoutT *l, uint16_t p, uint16_t x, uint16_t y) {
|
|
uint16_t c;
|
|
|
|
c = (uint16_t)(x >> 3);
|
|
return l->planes[p] + (uint32_t)y * l->rowBytes + (uint32_t)(c >> 1) * l->pairStep + (c & 1u);
|
|
}
|
|
|
|
|
|
// One on-surface rectangle: pasted on the planes and, a pixel at a time, on
|
|
// gRef, then compared everywhere; snapped back from the planes and compared
|
|
// with gRef's pixels at the rectangle's columns.
|
|
static bool planarCase(LayoutT *l, const CaseT *c, char *detail, size_t size) {
|
|
uint32_t bytes;
|
|
uint32_t i;
|
|
uint16_t stride;
|
|
uint16_t r;
|
|
uint16_t x;
|
|
uint16_t y;
|
|
uint16_t span;
|
|
uint16_t k;
|
|
uint8_t got;
|
|
|
|
stride = (uint16_t)(c->w + c->pad);
|
|
bytes = (uint32_t)stride * c->h;
|
|
span = c->doubleWide ? 2u : 1u;
|
|
for (i = 0; i < bytes; i++) {
|
|
gSrc[i] = (uint8_t)nextRandom();
|
|
}
|
|
planarStore(l, false);
|
|
for (y = 0; y < JL_SURFACE_HEIGHT; y++) {
|
|
for (x = 0; x < JL_SURFACE_WIDTH; x++) {
|
|
gRef[y][x] = (uint8_t)((x * BACK_X_MUL + y * BACK_Y_MUL) & 0x0F);
|
|
}
|
|
}
|
|
jlPlanarPasteIndexed(l->planes, l->rowBytes, l->pairStep, (uint16_t)c->x, (uint16_t)c->y, c->w, c->h, gSrc, stride, c->doubleWide);
|
|
for (r = 0; r < c->h; r++) {
|
|
for (i = 0; i < c->w; i++) {
|
|
for (k = 0; k < span; k++) {
|
|
gRef[c->y + r][c->x + i * span + k] = (uint8_t)(gSrc[r * stride + i] & 0x0Fu);
|
|
}
|
|
}
|
|
}
|
|
for (y = 0; y < JL_SURFACE_HEIGHT; y++) {
|
|
for (x = 0; x < JL_SURFACE_WIDTH; x++) {
|
|
got = planarGet(l, x, y);
|
|
if (got != gRef[y][x]) {
|
|
snprintf(detail, size, "%s paste at (%d,%d) w %u h %u%s: pixel (%u,%u) is %u, want %u", l->name, c->x, c->y, c->w, c->h, c->doubleWide ? " doubleWide" : "", x, y, got, gRef[y][x]);
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
memset(gSnap, CANARY, bytes);
|
|
jlPlanarSnapIndexed((const uint8_t *const *)l->planes, l->rowBytes, l->pairStep, (uint16_t)c->x, (uint16_t)c->y, c->w, c->h, gSnap, stride, c->doubleWide);
|
|
for (r = 0; r < c->h; r++) {
|
|
for (i = 0; i < stride; i++) {
|
|
got = gSnap[r * stride + i];
|
|
if (i < c->w ? got != gRef[c->y + r][c->x + i * span] : got != CANARY) {
|
|
snprintf(detail, size, "%s snap at (%d,%d) w %u h %u%s: byte %lu of row %u is %u", l->name, c->x, c->y, c->w, c->h, c->doubleWide ? " doubleWide" : "", (unsigned long)i, r, got);
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
static void planarSet(const LayoutT *l, uint16_t x, uint16_t y, uint8_t color) {
|
|
uint8_t *b;
|
|
uint16_t p;
|
|
uint8_t bit;
|
|
|
|
bit = (uint8_t)(0x80u >> (x & 7u));
|
|
for (p = 0; p < PLANAR_PLANES; p++) {
|
|
b = planarByte(l, p, x, y);
|
|
if (((color >> p) & 1u) != 0u) {
|
|
*b = (uint8_t)(*b | bit);
|
|
} else {
|
|
*b = (uint8_t)(*b & ~bit);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// Save the layout's background to gPlanarBack, or put it back.
|
|
static void planarStore(const LayoutT *l, bool save) {
|
|
uint8_t *buffer;
|
|
size_t bytes;
|
|
uint16_t p;
|
|
|
|
if (l->pairStep == ST_GROUP_BYTES) {
|
|
buffer = gInterleaved;
|
|
bytes = sizeof(gInterleaved);
|
|
if (save) {
|
|
memcpy(gPlanarBack[0], buffer, bytes);
|
|
} else {
|
|
memcpy(buffer, gPlanarBack[0], bytes);
|
|
}
|
|
return;
|
|
}
|
|
for (p = 0; p < PLANAR_PLANES; p++) {
|
|
bytes = sizeof(gSeparate[p]);
|
|
if (save) {
|
|
memcpy(gPlanarBack[p], gSeparate[p], bytes);
|
|
} else {
|
|
memcpy(gSeparate[p], gPlanarBack[p], bytes);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
static bool runCase(jlSurfaceT *stage, jlSurfaceT *ref, const jlSurfaceT *back, const CaseT *c, char *detail, size_t size) {
|
|
uint32_t bytes;
|
|
uint32_t i;
|
|
uint16_t stride;
|
|
|
|
stride = (uint16_t)(c->w + c->pad);
|
|
bytes = (uint32_t)stride * c->h;
|
|
for (i = 0; i < bytes; i++) {
|
|
gSrc[i] = (uint8_t)nextRandom();
|
|
}
|
|
jlSurfaceCopy(stage, back);
|
|
jlSurfaceCopy(ref, back);
|
|
jlSurfacePasteIndexed(stage, c->x, c->y, c->w, c->h, gSrc, stride, c->doubleWide);
|
|
pasteReference(ref, c, stride);
|
|
if (!comparePaste(stage, ref, c, detail, size)) {
|
|
return false;
|
|
}
|
|
memset(gSnap, CANARY, bytes);
|
|
jlSurfaceSnapIndexed(back, c->x, c->y, c->w, c->h, gSnap, stride, c->doubleWide);
|
|
return compareSnap(back, c, detail, size);
|
|
}
|
|
|
|
|
|
static bool runCases(jlSurfaceT *stage, jlSurfaceT *ref, const jlSurfaceT *back, bool random) {
|
|
CaseT c;
|
|
char detail[200];
|
|
uint16_t count;
|
|
uint16_t n;
|
|
|
|
detail[0] = '\0';
|
|
count = random ? (uint16_t)RANDOM_CASES : EDGE_CASE_COUNT;
|
|
for (n = 0; n < count; n++) {
|
|
if (random) {
|
|
c.x = (int16_t)(RANDOM_X_LOW + (int32_t)(nextRandom() % RANDOM_X_SPAN));
|
|
c.y = (int16_t)(RANDOM_Y_LOW + (int32_t)(nextRandom() % RANDOM_Y_SPAN));
|
|
c.w = (uint16_t)(nextRandom() % (RANDOM_W_MAX + 1u));
|
|
c.h = (uint16_t)(nextRandom() % (RANDOM_H_MAX + 1u));
|
|
c.pad = (uint16_t)(nextRandom() % (RANDOM_PAD_MAX + 1u));
|
|
c.doubleWide = (nextRandom() & 1u) != 0u;
|
|
} else {
|
|
c = kEdgeCases[n];
|
|
}
|
|
if (!runCase(stage, ref, back, &c, detail, sizeof(detail))) {
|
|
break;
|
|
}
|
|
}
|
|
if (n == count) {
|
|
snprintf(detail, sizeof(detail), "%u rectangles", count);
|
|
}
|
|
return check(random ? "random rectangles" : "edge rectangles", n == count, detail);
|
|
}
|
|
|
|
|
|
static bool runPlanar(LayoutT *l) {
|
|
CaseT c;
|
|
char detail[200];
|
|
char name[48];
|
|
uint16_t x;
|
|
uint16_t y;
|
|
uint16_t n;
|
|
uint16_t maxW;
|
|
|
|
detail[0] = '\0';
|
|
for (y = 0; y < JL_SURFACE_HEIGHT; y++) {
|
|
for (x = 0; x < JL_SURFACE_WIDTH; x++) {
|
|
planarSet(l, x, y, (uint8_t)((x * BACK_X_MUL + y * BACK_Y_MUL) & 0x0F));
|
|
}
|
|
}
|
|
planarStore(l, true);
|
|
for (n = 0; n < PLANAR_CASES; n++) {
|
|
c.doubleWide = (nextRandom() & 1u) != 0u;
|
|
c.x = (int16_t)(nextRandom() % JL_SURFACE_WIDTH);
|
|
if (c.doubleWide && c.x == JL_SURFACE_WIDTH - 1) {
|
|
c.x--;
|
|
}
|
|
maxW = (uint16_t)((JL_SURFACE_WIDTH - c.x) >> (c.doubleWide ? 1u : 0u));
|
|
// Mostly narrow (the edge columns), now and then the whole span left.
|
|
c.w = (uint16_t)(1u + nextRandom() % ((n & 3u) == 0u ? maxW : (maxW < 20u ? maxW : 20u)));
|
|
c.y = (int16_t)(nextRandom() % JL_SURFACE_HEIGHT);
|
|
c.h = (uint16_t)(1u + nextRandom() % PLANAR_H_MAX);
|
|
if (c.y + c.h > JL_SURFACE_HEIGHT) {
|
|
c.h = (uint16_t)(JL_SURFACE_HEIGHT - c.y);
|
|
}
|
|
c.pad = (uint16_t)(nextRandom() % (RANDOM_PAD_MAX + 1u));
|
|
if (!planarCase(l, &c, detail, sizeof(detail))) {
|
|
break;
|
|
}
|
|
}
|
|
if (n == PLANAR_CASES) {
|
|
snprintf(detail, sizeof(detail), "%u rectangles", n);
|
|
}
|
|
snprintf(name, sizeof(name), "planar %s", l->name);
|
|
return check(name, n == PLANAR_CASES, detail);
|
|
}
|
|
|
|
|
|
static uint8_t sampleWide(const jlSurfaceT *s, int32_t x, int32_t y) {
|
|
if (x < 0 || x >= JL_SURFACE_WIDTH || y < 0 || y >= JL_SURFACE_HEIGHT) {
|
|
return 0u;
|
|
}
|
|
return jlSamplePixel(s, (int16_t)x, (int16_t)y);
|
|
}
|
|
|
|
|
|
int main(void) {
|
|
LayoutT separate;
|
|
LayoutT interleaved;
|
|
jlConfigT config;
|
|
jlSurfaceT *stage;
|
|
jlSurfaceT *ref;
|
|
jlSurfaceT *back;
|
|
uint16_t p;
|
|
bool ok;
|
|
|
|
config.codegenBytes = 0u;
|
|
config.noAudio = true;
|
|
if (!jlInit(&config)) {
|
|
printf("indexedHost: FAIL -- jlInit: %s\n", jlLastError());
|
|
return 1;
|
|
}
|
|
stage = jlStageGet();
|
|
ref = jlSurfaceCreate();
|
|
back = jlSurfaceCreate();
|
|
if (ref == NULL || back == NULL) {
|
|
printf("indexedHost: FAIL -- jlSurfaceCreate: %s\n", jlLastError());
|
|
jlShutdown();
|
|
return 1;
|
|
}
|
|
fillBackground(back);
|
|
printf("indexedHost: indexed paste and snap, chunky and planar, against pixel-by-pixel references\n");
|
|
ok = true;
|
|
ok &= runCases(stage, ref, back, false);
|
|
ok &= runCases(stage, ref, back, true);
|
|
separate.name = "separate planes";
|
|
separate.rowBytes = PLANAR_ROW_BYTES;
|
|
separate.pairStep = PLANAR_SEPARATE_PAIR_STEP;
|
|
interleaved.name = "interleaved planes";
|
|
interleaved.rowBytes = ST_ROW_BYTES;
|
|
interleaved.pairStep = ST_GROUP_BYTES;
|
|
for (p = 0; p < PLANAR_PLANES; p++) {
|
|
separate.planes[p] = gSeparate[p];
|
|
interleaved.planes[p] = gInterleaved + p * sizeof(uint16_t);
|
|
}
|
|
ok &= runPlanar(&separate);
|
|
ok &= runPlanar(&interleaved);
|
|
jlSurfaceDestroy(back);
|
|
jlSurfaceDestroy(ref);
|
|
jlShutdown();
|
|
printf("indexedHost: %s\n", ok ? "PASS" : "FAIL");
|
|
return ok ? 0 : 1;
|
|
}
|