Commit 8f733a3a authored by Kenneth Moreland's avatar Kenneth Moreland
Browse files

Added icetSparseImageCopyPixels.

parent 445a7988
......@@ -78,6 +78,31 @@ static void ICET_TEST_SPARSE_IMAGE_HEADER(IceTSparseImage image)
static IceTSizeType colorPixelSize(IceTEnum color_format);
static IceTSizeType depthPixelSize(IceTEnum depth_format);
/* Given a pointer to a data element in a sparse image data buffer, the amount
of inactive pixels before this data element, and the number of active pixels
until the next run length, advance the pointer for the number of pixels given
and update the inactive and active parameters. Note that the pointer may
point to a run length entry if the number of active is set to zero. If
out_data_p is non-NULL, the data will also be written, in sparse format, to
the data pointed there and advanced. It is up to the calling method to
handle the sparse image header. */
static void icetSparseImageSkipPixels(const IceTVoid **data_p,
IceTSizeType *inactive_before_p,
IceTSizeType *active_till_next_runl_p,
IceTSizeType pixels_to_skip,
IceTSizeType pixel_size,
IceTVoid **out_data_p);
/* Similar calling structure as icetSparseImageSkipPixels except that the
data is also copied to out_image. */
static void icetSparseImageCopyPixelsInternal(
const IceTVoid **data_p,
IceTSizeType *inactive_before_p,
IceTSizeType *active_till_next_runl_p,
IceTSizeType pixels_to_copy,
IceTSizeType pixel_size,
IceTSparseImage out_image);
/* Renders the geometry for a tile and returns an image of the rendered data.
If IceT determines that it is most efficient to render the data directly to
the tile projection, then screen_viewport and tile_viewport will be set to
......@@ -1067,6 +1092,123 @@ IceTSparseImage icetSparseImageUnpackageFromReceive(IceTVoid *buffer)
return image;
}
static void icetSparseImageSkipPixels(const IceTVoid **data_p,
IceTSizeType *inactive_before_p,
IceTSizeType *active_till_next_runl_p,
IceTSizeType pixels_to_skip,
IceTSizeType pixel_size,
IceTVoid **out_data_p)
{
const IceTByte *data = *data_p; /* IceTByte for byte-pointer arithmetic. */
IceTSizeType inactive_before = *inactive_before_p;
IceTSizeType active_till_next_runl = *active_till_next_runl_p;
IceTSizeType pixels_left = pixels_to_skip;
IceTByte *out_data = (out_data_p ? *out_data_p : NULL);
while (pixels_left > 0) {
IceTSizeType count;
if ((inactive_before == 0) && (active_till_next_runl == 0)) {
inactive_before = INACTIVE_RUN_LENGTH(data);
active_till_next_runl = ACTIVE_RUN_LENGTH(data);
data += RUN_LENGTH_SIZE;
}
count = MIN(inactive_before, pixels_left);
inactive_before -= count;
pixels_left -= count;
if (out_data) {
INACTIVE_RUN_LENGTH(out_data) = count;
}
count = MIN(active_till_next_runl, pixels_left);
active_till_next_runl -= count;
pixels_left -= count;
if (out_data) {
ACTIVE_RUN_LENGTH(out_data) = count;
out_data += RUN_LENGTH_SIZE;
memcpy(out_data, data, pixel_size * count);
out_data += pixel_size * count;
}
data += pixel_size * count;
}
*data_p = data;
*inactive_before_p = inactive_before;
*active_till_next_runl_p = active_till_next_runl;
if (out_data_p) *out_data_p = out_data;
}
static void icetSparseImageCopyPixelsInternal(
const IceTVoid **in_data_p,
IceTSizeType *inactive_before_p,
IceTSizeType *active_till_next_runl_p,
IceTSizeType pixels_to_copy,
IceTSizeType pixel_size,
IceTSparseImage out_image)
{
IceTVoid *out_data = ICET_IMAGE_DATA(out_image);
icetSparseImageSetDimensions(out_image, pixels_to_copy, 1);
icetSparseImageSkipPixels(in_data_p,
inactive_before_p,
active_till_next_runl_p,
pixels_to_copy,
pixel_size,
&out_data);
{
/* Compute the actual number of bytes used to store the image. */
IceTPointerArithmetic buffer_begin
=(IceTPointerArithmetic)ICET_IMAGE_HEADER(out_image);
IceTPointerArithmetic buffer_end
=(IceTPointerArithmetic)out_data;
IceTPointerArithmetic compressed_size = buffer_end - buffer_begin;
ICET_IMAGE_HEADER(out_image)[ICET_IMAGE_ACTUAL_BUFFER_SIZE_INDEX]
= (IceTInt)compressed_size;
}
}
void icetSparseImageCopyPixels(const IceTSparseImage in_image,
IceTSizeType in_offset,
IceTSizeType num_pixels,
IceTSparseImage out_image)
{
IceTEnum color_format;
IceTEnum depth_format;
IceTSizeType pixel_size;
const IceTVoid *in_data;
IceTSizeType start_inactive;
IceTSizeType start_active;
color_format = icetSparseImageGetColorFormat(in_image);
depth_format = icetSparseImageGetDepthFormat(in_image);
if ( (color_format != icetSparseImageGetColorFormat(out_image))
|| (depth_format != icetSparseImageGetDepthFormat(out_image)) ) {
icetRaiseError("Cannot copy pixels of images with different formats.",
ICET_INVALID_VALUE);
return;
}
pixel_size = colorPixelSize(color_format) + depthPixelSize(depth_format);
in_data = ICET_IMAGE_DATA(in_image);
start_inactive = start_active = 0;
icetSparseImageSkipPixels(&in_data,
&start_inactive,
&start_active,
in_offset,
pixel_size,
NULL);
icetSparseImageCopyPixelsInternal(&in_data,
&start_inactive,
&start_active,
num_pixels,
pixel_size,
out_image);
}
void icetClearImage(IceTImage image)
{
IceTInt region[4] = {0, 0, 0, 0};
......
......@@ -99,6 +99,11 @@ ICET_EXPORT void icetSparseImagePackageForSend(IceTSparseImage image,
ICET_EXPORT IceTSparseImage icetSparseImageUnpackageFromReceive(
IceTVoid *buffer);
ICET_EXPORT void icetSparseImageCopyPixels(const IceTSparseImage in_image,
IceTSizeType in_offset,
IceTSizeType num_pixels,
IceTSparseImage out_image);
ICET_EXPORT void icetClearImage(IceTImage image);
ICET_EXPORT void icetClearSparseImage(IceTSparseImage image);
......
......@@ -20,6 +20,7 @@ SET(MyTests
CompressionSize.c
OddImageSizes.c
SimpleTiming.c
SparseImageCopy.c
)
IF (ICET_TESTS_USE_OPENGL)
......
/* -*- c -*- *****************************************************************
** Copyright (C) 2011 Sandia Corporation
** Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
** the U.S. Government retains certain rights in this software.
**
** This source code is released under the New BSD License.
**
** This test checks the behavior of various ways to copy blocks of pixels
** in sparse images.
*****************************************************************************/
#include "test_codes.h"
#include "test-util.h"
#include <IceTDevImage.h>
#include <stdlib.h>
#include <stdio.h>
/* Encode image position in color. */
#define ACTIVE_COLOR(x, y) \
((((x) & 0xFFFF) | 0x8000) | ((((y) & 0xFFFF) | 0x8000) << 16))
/* Fills the given image to have data in the lower triangle like this:
*
* +-------------+
* | \ |
* | \ |
* | \ |
* | \ |
* | \ |
* +-------------+
*
* Where the lower half is filled with data and the upper half is background. */
static void LowerTriangleImage(IceTImage image)
{
IceTUInt *data = icetImageGetColorui(image);
IceTSizeType width = icetImageGetWidth(image);
IceTSizeType height = icetImageGetHeight(image);
IceTSizeType x, y;
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
if (x < (height-y)) {
data[0] = ACTIVE_COLOR(x, y);
} else {
data[0] = 0;
}
data++;
}
}
}
/* Fills the given image to have data in the upper triangle like this:
*
* +-------------+
* | \ |
* | \ |
* | \ |
* | \ |
* | \ |
* +-------------+
*
* Where the upper half is filled with data and the upper half is background. */
static void UpperTriangleImage(IceTImage image)
{
IceTUInt *data = icetImageGetColorui(image);
IceTSizeType width = icetImageGetWidth(image);
IceTSizeType height = icetImageGetHeight(image);
IceTSizeType x, y;
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
if ((height-y) < x) {
data[0] = ACTIVE_COLOR(x, y);
} else {
data[0] = 0;
}
data++;
}
}
}
static int CompareSparseImages(const IceTSparseImage image1,
const IceTSparseImage image2)
{
/* This is a little bit hacky, but the sparse image internals are never
* exposed. */
IceTUInt *buffer1;
IceTUInt *buffer2;
IceTSizeType buffer_size1;
IceTSizeType buffer_size2;
IceTSizeType entries;
IceTSizeType i;
icetSparseImagePackageForSend(image1, (IceTVoid**)&buffer1, &buffer_size1);
icetSparseImagePackageForSend(image2, (IceTVoid**)&buffer2, &buffer_size2);
if (buffer_size1 != buffer_size2) {
printf("Buffer sizes do not match: %d vs %d!\n",
buffer_size1, buffer_size2);
return TEST_FAILED;
}
entries = buffer_size1/sizeof(IceTUInt);
for (i = 0; i < entries; i++) {
if (buffer1[i] != buffer2[i]) {
printf("Buffer mismatch at uint %d\n", i);
printf("0x%x vs 0x%x\n", buffer1[i], buffer2[i]);
return TEST_FAILED;
}
}
return TEST_PASSED;
}
static int TrySparseImageCopyPixels(const IceTImage image,
IceTSizeType start,
IceTSizeType end)
{
IceTVoid *full_sparse_buffer;
IceTSparseImage full_sparse;
IceTVoid *compress_sub_buffer;
IceTSparseImage compress_sub;
IceTVoid *sparse_copy_buffer;
IceTSparseImage sparse_copy;
IceTSizeType width = icetImageGetWidth(image);
IceTSizeType height = icetImageGetHeight(image);
IceTSizeType sub_size = end - start;
int result;
printf("Trying sparse image copy from %d to %d\n", start, end);
full_sparse_buffer = malloc(icetSparseImageBufferSize(width, height));
full_sparse = icetSparseImageAssignBuffer(full_sparse_buffer,width,height);
compress_sub_buffer = malloc(icetSparseImageBufferSize(sub_size, 1));
compress_sub = icetSparseImageAssignBuffer(compress_sub_buffer,
sub_size, 1);
sparse_copy_buffer = malloc(icetSparseImageBufferSize(sub_size, 1));
sparse_copy = icetSparseImageAssignBuffer(sparse_copy_buffer,
sub_size, 1);
icetCompressSubImage(image, start, sub_size, compress_sub);
icetCompressImage(image, full_sparse);
icetSparseImageCopyPixels(full_sparse, start, sub_size, sparse_copy);
result = CompareSparseImages(compress_sub, sparse_copy);
free(full_sparse_buffer);
free(compress_sub_buffer);
free(sparse_copy_buffer);
return result;
}
static int TestSparseImageCopyPixels(const IceTImage image)
{
#define NUM_OFFSETS 7
IceTSizeType interesting_offset[NUM_OFFSETS];
IceTSizeType width = icetImageGetWidth(image);
IceTSizeType height = icetImageGetHeight(image);
int start, end;
if (height <= 20) {
printf("Need image height greater than 20.\n");
return TEST_NOT_RUN;
}
interesting_offset[0] = 0; /* First pixel. */
interesting_offset[1] = 10*width; /* Some pixels up at left. */
interesting_offset[2] = 10*width + width/2; /* A bit up in the middle. */
interesting_offset[3] = width*(height/2) + height/2; /* Middle at triangle diagonal. */
interesting_offset[4] = width*(height-10); /* Some pixels from top at left. */
interesting_offset[5] = width*(height-10) + width/2; /* Some pixels from top in middle. */
interesting_offset[6] = width*height; /* Last pixel. */
for (start = 0; start < NUM_OFFSETS; start++) {
for (end = start+1; end < NUM_OFFSETS; end++) {
int result;
result = TrySparseImageCopyPixels(image,
interesting_offset[start],
interesting_offset[end]);
if (result != TEST_PASSED) return result;
}
}
return TEST_PASSED;
}
static int SparseImageCopyRun()
{
IceTVoid *imagebuffer;
IceTImage image;
icetSetColorFormat(ICET_IMAGE_COLOR_RGBA_UBYTE);
icetSetDepthFormat(ICET_IMAGE_DEPTH_NONE);
icetCompositeMode(ICET_COMPOSITE_MODE_BLEND);
imagebuffer = malloc(icetImageBufferSize(SCREEN_WIDTH, SCREEN_HEIGHT));
image = icetImageAssignBuffer(imagebuffer, SCREEN_WIDTH, SCREEN_HEIGHT);
printf("\n********* Creating lower triangle image\n");
LowerTriangleImage(image);
if (TestSparseImageCopyPixels(image) != TEST_PASSED) {
return TEST_FAILED;
}
printf("\n********* Creating upper triangle image\n");
UpperTriangleImage(image);
if (TestSparseImageCopyPixels(image) != TEST_PASSED) {
return TEST_FAILED;
}
free(imagebuffer);
return TEST_PASSED;
}
int SparseImageCopy(int argc, char *argv[])
{
/* To remove warning */
(void)argc;
(void)argv;
return run_test(SparseImageCopyRun);
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment