Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1901 serge 1
/*
2
 * Mesa 3-D graphics library
3
 * Version:  7.1
4
 *
5
 * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
6
 *
7
 * Permission is hereby granted, free of charge, to any person obtaining a
8
 * copy of this software and associated documentation files (the "Software"),
9
 * to deal in the Software without restriction, including without limitation
10
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11
 * and/or sell copies of the Software, and to permit persons to whom the
12
 * Software is furnished to do so, subject to the following conditions:
13
 *
14
 * The above copyright notice and this permission notice shall be included
15
 * in all copies or substantial portions of the Software.
16
 *
17
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20
 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
 */
24
 
25
#include "main/glheader.h"
26
#include "main/macros.h"
27
#include "main/imports.h"
28
#include "main/colormac.h"
29
 
30
#include "s_context.h"
31
#include "s_span.h"
32
#include "s_stencil.h"
33
#include "s_zoom.h"
34
 
35
 
36
/**
37
 * Compute the bounds of the region resulting from zooming a pixel span.
38
 * The resulting region will be entirely inside the window/scissor bounds
39
 * so no additional clipping is needed.
40
 * \param imageX, imageY  position of the mage being drawn (gl WindowPos)
41
 * \param spanX, spanY  position of span being drawing
42
 * \param width  number of pixels in span
43
 * \param x0, x1  returned X bounds of zoomed region [x0, x1)
44
 * \param y0, y1  returned Y bounds of zoomed region [y0, y1)
45
 * \return GL_TRUE if any zoomed pixels visible, GL_FALSE if totally clipped
46
 */
47
static GLboolean
48
compute_zoomed_bounds(struct gl_context *ctx, GLint imageX, GLint imageY,
49
                      GLint spanX, GLint spanY, GLint width,
50
                      GLint *x0, GLint *x1, GLint *y0, GLint *y1)
51
{
52
   const struct gl_framebuffer *fb = ctx->DrawBuffer;
53
   GLint c0, c1, r0, r1;
54
 
55
   ASSERT(spanX >= imageX);
56
   ASSERT(spanY >= imageY);
57
 
58
   /*
59
    * Compute destination columns: [c0, c1)
60
    */
61
   c0 = imageX + (GLint) ((spanX - imageX) * ctx->Pixel.ZoomX);
62
   c1 = imageX + (GLint) ((spanX + width - imageX) * ctx->Pixel.ZoomX);
63
   if (c1 < c0) {
64
      /* swap */
65
      GLint tmp = c1;
66
      c1 = c0;
67
      c0 = tmp;
68
   }
69
   c0 = CLAMP(c0, fb->_Xmin, fb->_Xmax);
70
   c1 = CLAMP(c1, fb->_Xmin, fb->_Xmax);
71
   if (c0 == c1) {
72
      return GL_FALSE; /* no width */
73
   }
74
 
75
   /*
76
    * Compute destination rows: [r0, r1)
77
    */
78
   r0 = imageY + (GLint) ((spanY - imageY) * ctx->Pixel.ZoomY);
79
   r1 = imageY + (GLint) ((spanY + 1 - imageY) * ctx->Pixel.ZoomY);
80
   if (r1 < r0) {
81
      /* swap */
82
      GLint tmp = r1;
83
      r1 = r0;
84
      r0 = tmp;
85
   }
86
   r0 = CLAMP(r0, fb->_Ymin, fb->_Ymax);
87
   r1 = CLAMP(r1, fb->_Ymin, fb->_Ymax);
88
   if (r0 == r1) {
89
      return GL_FALSE; /* no height */
90
   }
91
 
92
   *x0 = c0;
93
   *x1 = c1;
94
   *y0 = r0;
95
   *y1 = r1;
96
 
97
   return GL_TRUE;
98
}
99
 
100
 
101
/**
102
 * Convert a zoomed x image coordinate back to an unzoomed x coord.
103
 * 'zx' is screen position of a pixel in the zoomed image, who's left edge
104
 * is at 'imageX'.
105
 * return corresponding x coord in the original, unzoomed image.
106
 * This can use this for unzooming X or Y values.
107
 */
108
static INLINE GLint
109
unzoom_x(GLfloat zoomX, GLint imageX, GLint zx)
110
{
111
   /*
112
   zx = imageX + (x - imageX) * zoomX;
113
   zx - imageX = (x - imageX) * zoomX;
114
   (zx - imageX) / zoomX = x - imageX;
115
   */
116
   GLint x;
117
   if (zoomX < 0.0)
118
      zx++;
119
   x = imageX + (GLint) ((zx - imageX) / zoomX);
120
   return x;
121
}
122
 
123
 
124
 
125
/**
126
 * Helper function called from _swrast_write_zoomed_rgba/rgb/
127
 * index/depth_span().
128
 */
129
static void
130
zoom_span( struct gl_context *ctx, GLint imgX, GLint imgY, const SWspan *span,
131
           const GLvoid *src, GLenum format )
132
{
133
   SWcontext *swrast = SWRAST_CONTEXT(ctx);
134
   SWspan zoomed;
135
   GLint x0, x1, y0, y1;
136
   GLint zoomedWidth;
137
 
138
   if (!compute_zoomed_bounds(ctx, imgX, imgY, span->x, span->y, span->end,
139
                              &x0, &x1, &y0, &y1)) {
140
      return;  /* totally clipped */
141
   }
142
 
143
   if (!swrast->ZoomedArrays) {
144
      /* allocate on demand */
145
      swrast->ZoomedArrays = (SWspanarrays *) CALLOC(sizeof(SWspanarrays));
146
      if (!swrast->ZoomedArrays)
147
         return;
148
   }
149
 
150
   zoomedWidth = x1 - x0;
151
   ASSERT(zoomedWidth > 0);
152
   ASSERT(zoomedWidth <= MAX_WIDTH);
153
 
154
   /* no pixel arrays! must be horizontal spans. */
155
   ASSERT((span->arrayMask & SPAN_XY) == 0);
156
   ASSERT(span->primitive == GL_BITMAP);
157
 
158
   INIT_SPAN(zoomed, GL_BITMAP);
159
   zoomed.x = x0;
160
   zoomed.end = zoomedWidth;
161
   zoomed.array = swrast->ZoomedArrays;
162
   zoomed.array->ChanType = span->array->ChanType;
163
   if (zoomed.array->ChanType == GL_UNSIGNED_BYTE)
164
      zoomed.array->rgba = (GLchan (*)[4]) zoomed.array->rgba8;
165
   else if (zoomed.array->ChanType == GL_UNSIGNED_SHORT)
166
      zoomed.array->rgba = (GLchan (*)[4]) zoomed.array->rgba16;
167
   else
168
      zoomed.array->rgba = (GLchan (*)[4]) zoomed.array->attribs[FRAG_ATTRIB_COL0];
169
 
170
   COPY_4V(zoomed.attrStart[FRAG_ATTRIB_WPOS], span->attrStart[FRAG_ATTRIB_WPOS]);
171
   COPY_4V(zoomed.attrStepX[FRAG_ATTRIB_WPOS], span->attrStepX[FRAG_ATTRIB_WPOS]);
172
   COPY_4V(zoomed.attrStepY[FRAG_ATTRIB_WPOS], span->attrStepY[FRAG_ATTRIB_WPOS]);
173
 
174
   zoomed.attrStart[FRAG_ATTRIB_FOGC][0] = span->attrStart[FRAG_ATTRIB_FOGC][0];
175
   zoomed.attrStepX[FRAG_ATTRIB_FOGC][0] = span->attrStepX[FRAG_ATTRIB_FOGC][0];
176
   zoomed.attrStepY[FRAG_ATTRIB_FOGC][0] = span->attrStepY[FRAG_ATTRIB_FOGC][0];
177
 
178
   if (format == GL_RGBA || format == GL_RGB) {
179
      /* copy Z info */
180
      zoomed.z = span->z;
181
      zoomed.zStep = span->zStep;
182
      /* we'll generate an array of colorss */
183
      zoomed.interpMask = span->interpMask & ~SPAN_RGBA;
184
      zoomed.arrayMask |= SPAN_RGBA;
185
      zoomed.arrayAttribs |= FRAG_BIT_COL0;  /* we'll produce these values */
186
      ASSERT(span->arrayMask & SPAN_RGBA);
187
   }
188
   else if (format == GL_DEPTH_COMPONENT) {
189
      /* Copy color info */
190
      zoomed.red = span->red;
191
      zoomed.green = span->green;
192
      zoomed.blue = span->blue;
193
      zoomed.alpha = span->alpha;
194
      zoomed.redStep = span->redStep;
195
      zoomed.greenStep = span->greenStep;
196
      zoomed.blueStep = span->blueStep;
197
      zoomed.alphaStep = span->alphaStep;
198
      /* we'll generate an array of depth values */
199
      zoomed.interpMask = span->interpMask & ~SPAN_Z;
200
      zoomed.arrayMask |= SPAN_Z;
201
      ASSERT(span->arrayMask & SPAN_Z);
202
   }
203
   else {
204
      _mesa_problem(ctx, "Bad format in zoom_span");
205
      return;
206
   }
207
 
208
   /* zoom the span horizontally */
209
   if (format == GL_RGBA) {
210
      if (zoomed.array->ChanType == GL_UNSIGNED_BYTE) {
211
         const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) src;
212
         GLint i;
213
         for (i = 0; i < zoomedWidth; i++) {
214
            GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x;
215
            ASSERT(j >= 0);
216
            ASSERT(j < (GLint) span->end);
217
            COPY_4UBV(zoomed.array->rgba8[i], rgba[j]);
218
         }
219
      }
220
      else if (zoomed.array->ChanType == GL_UNSIGNED_SHORT) {
221
         const GLushort (*rgba)[4] = (const GLushort (*)[4]) src;
222
         GLint i;
223
         for (i = 0; i < zoomedWidth; i++) {
224
            GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x;
225
            ASSERT(j >= 0);
226
            ASSERT(j < (GLint) span->end);
227
            COPY_4V(zoomed.array->rgba16[i], rgba[j]);
228
         }
229
      }
230
      else {
231
         const GLfloat (*rgba)[4] = (const GLfloat (*)[4]) src;
232
         GLint i;
233
         for (i = 0; i < zoomedWidth; i++) {
234
            GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x;
235
            ASSERT(j >= 0);
236
            ASSERT(j < span->end);
237
            COPY_4V(zoomed.array->attribs[FRAG_ATTRIB_COL0][i], rgba[j]);
238
         }
239
      }
240
   }
241
   else if (format == GL_RGB) {
242
      if (zoomed.array->ChanType == GL_UNSIGNED_BYTE) {
243
         const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) src;
244
         GLint i;
245
         for (i = 0; i < zoomedWidth; i++) {
246
            GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x;
247
            ASSERT(j >= 0);
248
            ASSERT(j < (GLint) span->end);
249
            zoomed.array->rgba8[i][0] = rgb[j][0];
250
            zoomed.array->rgba8[i][1] = rgb[j][1];
251
            zoomed.array->rgba8[i][2] = rgb[j][2];
252
            zoomed.array->rgba8[i][3] = 0xff;
253
         }
254
      }
255
      else if (zoomed.array->ChanType == GL_UNSIGNED_SHORT) {
256
         const GLushort (*rgb)[3] = (const GLushort (*)[3]) src;
257
         GLint i;
258
         for (i = 0; i < zoomedWidth; i++) {
259
            GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x;
260
            ASSERT(j >= 0);
261
            ASSERT(j < (GLint) span->end);
262
            zoomed.array->rgba16[i][0] = rgb[j][0];
263
            zoomed.array->rgba16[i][1] = rgb[j][1];
264
            zoomed.array->rgba16[i][2] = rgb[j][2];
265
            zoomed.array->rgba16[i][3] = 0xffff;
266
         }
267
      }
268
      else {
269
         const GLfloat (*rgb)[3] = (const GLfloat (*)[3]) src;
270
         GLint i;
271
         for (i = 0; i < zoomedWidth; i++) {
272
            GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x;
273
            ASSERT(j >= 0);
274
            ASSERT(j < span->end);
275
            zoomed.array->attribs[FRAG_ATTRIB_COL0][i][0] = rgb[j][0];
276
            zoomed.array->attribs[FRAG_ATTRIB_COL0][i][1] = rgb[j][1];
277
            zoomed.array->attribs[FRAG_ATTRIB_COL0][i][2] = rgb[j][2];
278
            zoomed.array->attribs[FRAG_ATTRIB_COL0][i][3] = 1.0F;
279
         }
280
      }
281
   }
282
   else if (format == GL_DEPTH_COMPONENT) {
283
      const GLuint *zValues = (const GLuint *) src;
284
      GLint i;
285
      for (i = 0; i < zoomedWidth; i++) {
286
         GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - span->x;
287
         ASSERT(j >= 0);
288
         ASSERT(j < (GLint) span->end);
289
         zoomed.array->z[i] = zValues[j];
290
      }
291
      /* Now, fall into the RGB path below */
292
      format = GL_RGBA;
293
   }
294
 
295
   /* write the span in rows [r0, r1) */
296
   if (format == GL_RGBA || format == GL_RGB) {
297
      /* Writing the span may modify the colors, so make a backup now if we're
298
       * going to call _swrast_write_zoomed_span() more than once.
299
       * Also, clipping may change the span end value, so store it as well.
300
       */
301
      const GLint end = zoomed.end; /* save */
302
      GLuint rgbaSave[MAX_WIDTH][4];
303
      const GLint pixelSize =
304
         (zoomed.array->ChanType == GL_UNSIGNED_BYTE) ? 4 * sizeof(GLubyte) :
305
         ((zoomed.array->ChanType == GL_UNSIGNED_SHORT) ? 4 * sizeof(GLushort)
306
          : 4 * sizeof(GLfloat));
307
      if (y1 - y0 > 1) {
308
         memcpy(rgbaSave, zoomed.array->rgba, zoomed.end * pixelSize);
309
      }
310
      for (zoomed.y = y0; zoomed.y < y1; zoomed.y++) {
311
         _swrast_write_rgba_span(ctx, &zoomed);
312
         zoomed.end = end;  /* restore */
313
         if (y1 - y0 > 1) {
314
            /* restore the colors */
315
            memcpy(zoomed.array->rgba, rgbaSave, zoomed.end * pixelSize);
316
         }
317
      }
318
   }
319
}
320
 
321
 
322
void
323
_swrast_write_zoomed_rgba_span(struct gl_context *ctx, GLint imgX, GLint imgY,
324
                               const SWspan *span, const GLvoid *rgba)
325
{
326
   zoom_span(ctx, imgX, imgY, span, rgba, GL_RGBA);
327
}
328
 
329
 
330
void
331
_swrast_write_zoomed_rgb_span(struct gl_context *ctx, GLint imgX, GLint imgY,
332
                              const SWspan *span, const GLvoid *rgb)
333
{
334
   zoom_span(ctx, imgX, imgY, span, rgb, GL_RGB);
335
}
336
 
337
 
338
void
339
_swrast_write_zoomed_depth_span(struct gl_context *ctx, GLint imgX, GLint imgY,
340
                                const SWspan *span)
341
{
342
   zoom_span(ctx, imgX, imgY, span,
343
             (const GLvoid *) span->array->z, GL_DEPTH_COMPONENT);
344
}
345
 
346
 
347
/**
348
 * Zoom/write stencil values.
349
 * No per-fragment operations are applied.
350
 */
351
void
352
_swrast_write_zoomed_stencil_span(struct gl_context *ctx, GLint imgX, GLint imgY,
353
                                  GLint width, GLint spanX, GLint spanY,
354
                                  const GLstencil stencil[])
355
{
356
   GLstencil zoomedVals[MAX_WIDTH];
357
   GLint x0, x1, y0, y1, y;
358
   GLint i, zoomedWidth;
359
 
360
   if (!compute_zoomed_bounds(ctx, imgX, imgY, spanX, spanY, width,
361
                              &x0, &x1, &y0, &y1)) {
362
      return;  /* totally clipped */
363
   }
364
 
365
   zoomedWidth = x1 - x0;
366
   ASSERT(zoomedWidth > 0);
367
   ASSERT(zoomedWidth <= MAX_WIDTH);
368
 
369
   /* zoom the span horizontally */
370
   for (i = 0; i < zoomedWidth; i++) {
371
      GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - spanX;
372
      ASSERT(j >= 0);
373
      ASSERT(j < width);
374
      zoomedVals[i] = stencil[j];
375
   }
376
 
377
   /* write the zoomed spans */
378
   for (y = y0; y < y1; y++) {
379
      _swrast_write_stencil_span(ctx, zoomedWidth, x0, y, zoomedVals);
380
   }
381
}
382
 
383
 
384
/**
385
 * Zoom/write z values (16 or 32-bit).
386
 * No per-fragment operations are applied.
387
 */
388
void
389
_swrast_write_zoomed_z_span(struct gl_context *ctx, GLint imgX, GLint imgY,
390
                            GLint width, GLint spanX, GLint spanY,
391
                            const GLvoid *z)
392
{
393
   struct gl_renderbuffer *rb = ctx->DrawBuffer->_DepthBuffer;
394
   GLushort zoomedVals16[MAX_WIDTH];
395
   GLuint zoomedVals32[MAX_WIDTH];
396
   GLint x0, x1, y0, y1, y;
397
   GLint i, zoomedWidth;
398
 
399
   if (!compute_zoomed_bounds(ctx, imgX, imgY, spanX, spanY, width,
400
                              &x0, &x1, &y0, &y1)) {
401
      return;  /* totally clipped */
402
   }
403
 
404
   zoomedWidth = x1 - x0;
405
   ASSERT(zoomedWidth > 0);
406
   ASSERT(zoomedWidth <= MAX_WIDTH);
407
 
408
   /* zoom the span horizontally */
409
   if (rb->DataType == GL_UNSIGNED_SHORT) {
410
      for (i = 0; i < zoomedWidth; i++) {
411
         GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - spanX;
412
         ASSERT(j >= 0);
413
         ASSERT(j < width);
414
         zoomedVals16[i] = ((GLushort *) z)[j];
415
      }
416
      z = zoomedVals16;
417
   }
418
   else {
419
      ASSERT(rb->DataType == GL_UNSIGNED_INT);
420
      for (i = 0; i < zoomedWidth; i++) {
421
         GLint j = unzoom_x(ctx->Pixel.ZoomX, imgX, x0 + i) - spanX;
422
         ASSERT(j >= 0);
423
         ASSERT(j < width);
424
         zoomedVals32[i] = ((GLuint *) z)[j];
425
      }
426
      z = zoomedVals32;
427
   }
428
 
429
   /* write the zoomed spans */
430
   for (y = y0; y < y1; y++) {
431
      rb->PutRow(ctx, rb, zoomedWidth, x0, y, z, NULL);
432
   }
433
}