#include "glheader.h"
#include "macros.h"
#include "imports.h"
#include "colormac.h"
#include "s_context.h"
#include "s_span.h"
#include "s_stencil.h"
#include "s_zoom.h"
static GLboolean
compute_zoomed_bounds(GLcontext *ctx, GLint imageX, GLint imageY,
GLint spanX, GLint spanY, GLint width,
GLint *x0, GLint *x1, GLint *y0, GLint *y1)
{
const struct gl_framebuffer *fb = ctx->DrawBuffer;
GLint c0, c1, r0, r1;
ASSERT(spanX >= imageX);
ASSERT(spanY >= imageY);
c0 = imageX + (GLint) ((spanX - imageX) * ctx->Pixel.ZoomX);
c1 = imageX + (GLint) ((spanX + width - imageX) * ctx->Pixel.ZoomX);
if (c1 < c0) {
GLint tmp = c1;
c1 = c0;
c0 = tmp;
}
c0 = CLAMP(c0, fb->_Xmin, fb->_Xmax);
c1 = CLAMP(c1, fb->_Xmin, fb->_Xmax);
if (c0 == c1) {
return GL_FALSE;
}
r0 = imageY + (GLint) ((spanY - imageY) * ctx->Pixel.ZoomY);
r1 = imageY + (GLint) ((spanY + 1 - imageY) * ctx->Pixel.ZoomY);
if (r1 < r0) {
GLint tmp = r1;
r1 = r0;
r0 = tmp;
}
r0 = CLAMP(r0, fb->_Ymin, fb->_Ymax);
r1 = CLAMP(r1, fb->_Ymin, fb->_Ymax);
if (r0 == r1) {
return GL_FALSE;
}
*x0 = c0;
*x1 = c1;
*y0 = r0;
*y1 = r1;
return GL_TRUE;
}
static INLINE GLint
unzoom_x(GLfloat zoomX, GLint imageX, GLint zx)
{
GLint x = imageX + (GLint) ((zx - imageX) / zoomX);
return x;
}
static void
zoom_span( GLcontext *ctx, GLint imgX, GLint imgY, const SWspan *span,
const GLvoid *src, GLenum format )
{
SWspan zoomed;
SWspanarrays zoomed_arrays;
GLint x0, x1, y0, y1;
GLint zoomedWidth;
if (!compute_zoomed_bounds(ctx, imgX, imgY, span->x, span->y, span->end,
&x0, &x1, &y0, &y1)) {
return;
}
zoomedWidth = x1 - x0;
ASSERT(zoomedWidth > 0);
ASSERT(zoomedWidth <= MAX_WIDTH);
ASSERT((span->arrayMask & SPAN_XY) == 0);
ASSERT(span->primitive == GL_BITMAP);
INIT_SPAN(zoomed, GL_BITMAP, 0, 0, 0);
zoomed.x = x0;
zoomed.end = zoomedWidth;
zoomed.array = &zoomed_arrays;
zoomed_arrays.ChanType = span->array->ChanType;
#if CHAN_TYPE == GL_UNSIGNED_BYTE
zoomed_arrays.rgba = zoomed_arrays.color.sz1.rgba;
zoomed_arrays.spec = zoomed_arrays.color.sz1.spec;
#elif CHAN_TYPE == GL_UNSIGNED_SHORT
zoomed_arrays.rgba = zoomed_arrays.color.sz2.rgba;
zoomed_arrays.spec = zoomed_arrays.color.sz2.spec;
#else
zoomed_arrays.rgba = zoomed_arrays.color.sz4.rgba;
zoomed_arrays.spec = zoomed_arrays.color.sz4.spec;
#endif
zoomed.fog = span->fog;
zoomed.fogStep = span->fogStep;
if (format == GL_RGBA || format == GL_RGB) {
zoomed.z = span->z;
zoomed.zStep = span->zStep;
zoomed.interpMask = span->interpMask & ~SPAN_RGBA;
zoomed.arrayMask |= SPAN_RGBA;
ASSERT(span->arrayMask & SPAN_RGBA);
}
else if (format == GL_COLOR_INDEX) {
zoomed.z = span->z;
zoomed.zStep = span->zStep;
zoomed.interpMask = span->interpMask & ~SPAN_INDEX;
zoomed.arrayMask |= SPAN_INDEX;
ASSERT(span->arrayMask & SPAN_INDEX);
}
else if (format == GL_DEPTH_COMPONENT) {
zoomed.red = span->red;
zoomed.green = span->green;
zoomed.blue = span->blue;
zoomed.alpha = span->alpha;
zoomed.redStep = span->redStep;
zoomed.greenStep = span->greenStep;
zoomed.blueStep = span->blueStep;
zoomed.alphaStep = span->alphaStep;
zoomed.interpMask = span->interpMask & ~SPAN_Z;
zoomed.arrayMask |= SPAN_Z;
ASSERT(span->arrayMask & SPAN_Z);
}
else {
_mesa_problem(ctx, "Bad format in zoom_span");
return;
}
if (format == GL_RGBA) {
if (zoomed.array->ChanType == GL_UNSIGNED_BYTE) {
const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) src;
GLint i;
for (i = 0; i < zoomedWidth; i++) {
GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x;
ASSERT(j >= 0);
ASSERT(j < span->end);
COPY_4UBV(zoomed.array->color.sz1.rgba[i], rgba[j]);
}
}
else if (zoomed.array->ChanType == GL_UNSIGNED_SHORT) {
const GLushort (*rgba)[4] = (const GLushort (*)[4]) src;
GLint i;
for (i = 0; i < zoomedWidth; i++) {
GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x;
ASSERT(j >= 0);
ASSERT(j < span->end);
COPY_4V(zoomed.array->color.sz2.rgba[i], rgba[j]);
}
}
else {
const GLfloat (*rgba)[4] = (const GLfloat (*)[4]) src;
GLint i;
for (i = 0; i < zoomedWidth; i++) {
GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x;
ASSERT(j >= 0);
ASSERT(j < span->end);
COPY_4V(zoomed.array->color.sz4.rgba[i], rgba[j]);
}
}
}
else if (format == GL_RGB) {
if (zoomed.array->ChanType == GL_UNSIGNED_BYTE) {
const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) src;
GLint i;
for (i = 0; i < zoomedWidth; i++) {
GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x;
ASSERT(j >= 0);
ASSERT(j < span->end);
zoomed.array->color.sz1.rgba[i][0] = rgb[j][0];
zoomed.array->color.sz1.rgba[i][1] = rgb[j][1];
zoomed.array->color.sz1.rgba[i][2] = rgb[j][2];
zoomed.array->color.sz1.rgba[i][3] = 0xff;
}
}
else if (zoomed.array->ChanType == GL_UNSIGNED_SHORT) {
const GLushort (*rgb)[3] = (const GLushort (*)[3]) src;
GLint i;
for (i = 0; i < zoomedWidth; i++) {
GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x;
ASSERT(j >= 0);
ASSERT(j < span->end);
zoomed.array->color.sz2.rgba[i][0] = rgb[j][0];
zoomed.array->color.sz2.rgba[i][1] = rgb[j][1];
zoomed.array->color.sz2.rgba[i][2] = rgb[j][2];
zoomed.array->color.sz2.rgba[i][3] = 0xffff;
}
}
else {
const GLfloat (*rgb)[3] = (const GLfloat (*)[3]) src;
GLint i;
for (i = 0; i < zoomedWidth; i++) {
GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x;
ASSERT(j >= 0);
ASSERT(j < span->end);
zoomed.array->color.sz4.rgba[i][0] = rgb[j][0];
zoomed.array->color.sz4.rgba[i][1] = rgb[j][1];
zoomed.array->color.sz4.rgba[i][2] = rgb[j][2];
zoomed.array->color.sz4.rgba[i][3] = 1.0F;
}
}
}
else if (format == GL_COLOR_INDEX) {
const GLuint *indexes = (const GLuint *) src;
GLint i;
for (i = 0; i < zoomedWidth; i++) {
GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x;
ASSERT(j >= 0);
ASSERT(j < span->end);
zoomed.array->index[i] = indexes[j];
}
}
else if (format == GL_DEPTH_COMPONENT) {
const GLuint *zValues = (const GLuint *) src;
GLint i;
for (i = 0; i < zoomedWidth; i++) {
GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x;
ASSERT(j >= 0);
ASSERT(j < span->end);
zoomed.array->z[i] = zValues[j];
}
format = ctx->Visual.rgbMode ? GL_RGBA : GL_COLOR_INDEX;
}
if (format == GL_RGBA || format == GL_RGB) {
const GLint end = zoomed.end;
void *rgbaSave = zoomed.array->spec;
const GLint pixelSize =
(zoomed.array->ChanType == GL_UNSIGNED_BYTE) ? 4 * sizeof(GLubyte) :
((zoomed.array->ChanType == GL_UNSIGNED_SHORT) ? 4 * sizeof(GLushort)
: 4 * sizeof(GLfloat));
if (y1 - y0 > 1) {
MEMCPY(rgbaSave, zoomed.array->rgba, zoomed.end * pixelSize);
}
for (zoomed.y = y0; zoomed.y < y1; zoomed.y++) {
_swrast_write_rgba_span(ctx, &zoomed);
zoomed.end = end;
if (y1 - y0 > 1) {
MEMCPY(zoomed.array->rgba, rgbaSave, zoomed.end * pixelSize);
}
}
}
else if (format == GL_COLOR_INDEX) {
GLuint *indexSave = (GLuint *) zoomed.array->spec;
const GLint end = zoomed.end;
if (y1 - y0 > 1) {
MEMCPY(indexSave, zoomed.array->index, zoomed.end * sizeof(GLuint));
}
for (zoomed.y = y0; zoomed.y < y1; zoomed.y++) {
_swrast_write_index_span(ctx, &zoomed);
zoomed.end = end;
if (y1 - y0 > 1) {
MEMCPY(zoomed.array->index, indexSave, zoomed.end * sizeof(GLuint));
}
}
}
}
void
_swrast_write_zoomed_rgba_span(GLcontext *ctx, GLint imgX, GLint imgY,
const SWspan *span, const GLvoid *rgba)
{
zoom_span(ctx, imgX, imgY, span, rgba, GL_RGBA);
}
void
_swrast_write_zoomed_rgb_span(GLcontext *ctx, GLint imgX, GLint imgY,
const SWspan *span, const GLvoid *rgb)
{
zoom_span(ctx, imgX, imgY, span, rgb, GL_RGB);
}
void
_swrast_write_zoomed_index_span(GLcontext *ctx, GLint imgX, GLint imgY,
const SWspan *span)
{
zoom_span(ctx, imgX, imgY, span,
(const GLvoid *) span->array->index, GL_COLOR_INDEX);
}
void
_swrast_write_zoomed_depth_span(GLcontext *ctx, GLint imgX, GLint imgY,
const SWspan *span)
{
zoom_span(ctx, imgX, imgY, span,
(const GLvoid *) span->array->z, GL_DEPTH_COMPONENT);
}
void
_swrast_write_zoomed_stencil_span(GLcontext *ctx, GLint imgX, GLint imgY,
GLint width, GLint spanX, GLint spanY,
const GLstencil stencil[])
{
GLstencil zoomedVals[MAX_WIDTH];
GLint x0, x1, y0, y1, y;
GLint i, zoomedWidth;
if (!compute_zoomed_bounds(ctx, imgX, imgY, spanX, spanY, width,
&x0, &x1, &y0, &y1)) {
return;
}
zoomedWidth = x1 - x0;
ASSERT(zoomedWidth > 0);
ASSERT(zoomedWidth <= MAX_WIDTH);
for (i = 0; i < zoomedWidth; i++) {
GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - spanX;
ASSERT(j >= 0);
ASSERT(j < width);
zoomedVals[i] = stencil[j];
}
for (y = y0; y < y1; y++) {
_swrast_write_stencil_span(ctx, zoomedWidth, x0, y, zoomedVals);
}
}
void
_swrast_write_zoomed_z_span(GLcontext *ctx, GLint imgX, GLint imgY,
GLint width, GLint spanX, GLint spanY,
const GLvoid *z)
{
struct gl_renderbuffer *rb = ctx->DrawBuffer->_DepthBuffer;
GLushort zoomedVals16[MAX_WIDTH];
GLuint zoomedVals32[MAX_WIDTH];
GLint x0, x1, y0, y1, y;
GLint i, zoomedWidth;
if (!compute_zoomed_bounds(ctx, imgX, imgY, spanX, spanY, width,
&x0, &x1, &y0, &y1)) {
return;
}
zoomedWidth = x1 - x0;
ASSERT(zoomedWidth > 0);
ASSERT(zoomedWidth <= MAX_WIDTH);
if (rb->DataType == GL_UNSIGNED_SHORT) {
for (i = 0; i < zoomedWidth; i++) {
GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - spanX;
ASSERT(j >= 0);
ASSERT(j < width);
zoomedVals16[i] = ((GLushort *) z)[j];
}
z = zoomedVals16;
}
else {
ASSERT(rb->DataType == GL_UNSIGNED_INT);
for (i = 0; i < zoomedWidth; i++) {
GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - spanX;
ASSERT(j >= 0);
ASSERT(j < width);
zoomedVals32[i] = ((GLuint *) z)[j];
}
z = zoomedVals32;
}
for (y = y0; y < y1; y++) {
rb->PutRow(ctx, rb, zoomedWidth, x0, y, z, NULL);
}
}