xref: /reactos/dll/opengl/mesa/copypix.c (revision 5f2bebf7)
1 /* $Id: copypix.c,v 1.7 1998/02/03 23:45:02 brianp Exp $ */
2 
3 /*
4  * Mesa 3-D graphics library
5  * Version:  2.4
6  * Copyright (C) 1995-1996  Brian Paul
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the Free
20  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21  */
22 
23 
24 /*
25  * $Log: copypix.c,v $
26  * Revision 1.7  1998/02/03 23:45:02  brianp
27  * added casts to prevent warnings with Amiga StormC compiler
28  *
29  * Revision 1.6  1997/07/24 01:24:45  brianp
30  * changed precompiled header symbol from PCH to PC_HEADER
31  *
32  * Revision 1.5  1997/06/20 02:20:04  brianp
33  * replaced Current.IntColor with Current.ByteColor
34  *
35  * Revision 1.4  1997/05/28 03:23:48  brianp
36  * added precompiled header (PCH) support
37  *
38  * Revision 1.3  1996/09/15 14:18:10  brianp
39  * now use GLframebuffer and GLvisual
40  *
41  * Revision 1.2  1996/09/15 01:48:58  brianp
42  * removed #define NULL 0
43  *
44  * Revision 1.1  1996/09/13 01:38:16  brianp
45  * Initial revision
46  *
47  */
48 
49 
50 #ifdef PC_HEADER
51 #include "all.h"
52 #else
53 #include <string.h>
54 #include "context.h"
55 #include "copypix.h"
56 #include "depth.h"
57 #include "feedback.h"
58 #include "dlist.h"
59 #include "macros.h"
60 #include "pixel.h"
61 #include "span.h"
62 #include "stencil.h"
63 #include "types.h"
64 #endif
65 
66 
67 
copy_rgb_pixels(GLcontext * ctx,GLint srcx,GLint srcy,GLint width,GLint height,GLint destx,GLint desty)68 static void copy_rgb_pixels( GLcontext* ctx,
69                              GLint srcx, GLint srcy, GLint width, GLint height,
70                              GLint destx, GLint desty )
71 {
72    DEFARRAY( GLdepth, zspan, MAX_WIDTH );
73    DEFARRAY( GLubyte, red, MAX_WIDTH );
74    DEFARRAY( GLubyte, green, MAX_WIDTH );
75    DEFARRAY( GLubyte, blue, MAX_WIDTH );
76    DEFARRAY( GLubyte, alpha, MAX_WIDTH );
77    GLboolean scale_or_bias, quick_draw, zoom;
78    GLint sy, dy, stepy;
79    GLint i, j;
80    GLboolean setbuffer;
81 
82    if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
83       zoom = GL_FALSE;
84    }
85    else {
86       zoom = GL_TRUE;
87    }
88 
89    /* Determine if copy should be done bottom-to-top or top-to-bottom */
90    if (srcy<desty) {
91       /* top-down  max-to-min */
92       sy = srcy + height - 1;
93       dy = desty + height - 1;
94       stepy = -1;
95    }
96    else {
97       /* bottom-up  min-to-max */
98       sy = srcy;
99       dy = desty;
100       stepy = 1;
101    }
102 
103    scale_or_bias = ctx->Pixel.RedScale!=1.0 || ctx->Pixel.RedBias!=0.0
104                 || ctx->Pixel.GreenScale!=1.0 || ctx->Pixel.GreenBias!=0.0
105 		|| ctx->Pixel.BlueScale!=1.0 || ctx->Pixel.BlueBias!=0.0
106 		|| ctx->Pixel.AlphaScale!=1.0 || ctx->Pixel.AlphaBias!=0.0;
107 
108    if (ctx->Depth.Test) {
109       /* fill in array of z values */
110       GLint z = (GLint) (ctx->Current.RasterPos[2] * DEPTH_SCALE);
111       for (i=0;i<width;i++) {
112          zspan[i] = z;
113       }
114    }
115 
116    if (ctx->RasterMask==0 && !zoom
117        && destx>=0 && destx+width<=ctx->Buffer->Width) {
118       quick_draw = GL_TRUE;
119    }
120    else {
121       quick_draw = GL_FALSE;
122    }
123 
124    /* If read and draw buffer are different we must do buffer switching */
125    setbuffer = ctx->Pixel.ReadBuffer!=ctx->Color.DrawBuffer;
126 
127    for (j=0; j<height; j++, sy+=stepy, dy+=stepy) {
128       /* read */
129 
130       if (setbuffer) {
131          (*ctx->Driver.SetBuffer)( ctx, ctx->Pixel.ReadBuffer );
132       }
133       gl_read_color_span( ctx, width, srcx, sy, red, green, blue, alpha );
134 
135       if (scale_or_bias) {
136          GLfloat rbias = ctx->Pixel.RedBias   * ctx->Visual->RedScale;
137          GLfloat gbias = ctx->Pixel.GreenBias * ctx->Visual->GreenScale;
138          GLfloat bbias = ctx->Pixel.BlueBias  * ctx->Visual->BlueScale;
139          GLfloat abias = ctx->Pixel.AlphaBias * ctx->Visual->AlphaScale;
140          GLint rmax = (GLint) ctx->Visual->RedScale;
141          GLint gmax = (GLint) ctx->Visual->GreenScale;
142          GLint bmax = (GLint) ctx->Visual->BlueScale;
143          GLint amax = (GLint) ctx->Visual->AlphaScale;
144          for (i=0;i<width;i++) {
145             GLint r = red[i]   * ctx->Pixel.RedScale   + rbias;
146             GLint g = green[i] * ctx->Pixel.GreenScale + gbias;
147             GLint b = blue[i]  * ctx->Pixel.BlueScale  + bbias;
148             GLint a = alpha[i] * ctx->Pixel.AlphaScale + abias;
149             red[i]   = CLAMP( r, 0, rmax );
150             green[i] = CLAMP( g, 0, gmax );
151             blue[i]  = CLAMP( b, 0, bmax );
152             alpha[i] = CLAMP( a, 0, amax );
153          }
154       }
155 
156       if (ctx->Pixel.MapColorFlag) {
157          GLfloat r = (ctx->Pixel.MapRtoRsize-1) * ctx->Visual->InvRedScale;
158          GLfloat g = (ctx->Pixel.MapGtoGsize-1) * ctx->Visual->InvGreenScale;
159          GLfloat b = (ctx->Pixel.MapBtoBsize-1) * ctx->Visual->InvBlueScale;
160          GLfloat a = (ctx->Pixel.MapAtoAsize-1) * ctx->Visual->InvAlphaScale;
161          for (i=0;i<width;i++) {
162             GLint ir = red[i] * r;
163             GLint ig = green[i] * g;
164             GLint ib = blue[i] * b;
165             GLint ia = alpha[i] * a;
166             red[i]   = (GLint) (ctx->Pixel.MapRtoR[ir]*ctx->Visual->RedScale);
167             green[i] = (GLint) (ctx->Pixel.MapGtoG[ig]*ctx->Visual->GreenScale);
168             blue[i]  = (GLint) (ctx->Pixel.MapBtoB[ib]*ctx->Visual->BlueScale);
169             alpha[i] = (GLint) (ctx->Pixel.MapAtoA[ia]*ctx->Visual->AlphaScale);
170          }
171       }
172 
173       /* write */
174       if (setbuffer) {
175          (*ctx->Driver.SetBuffer)( ctx, ctx->Color.DrawBuffer );
176       }
177       if (quick_draw && dy>=0 && dy<ctx->Buffer->Height) {
178          (*ctx->Driver.WriteColorSpan)( ctx, width, destx, dy,
179                                  red, green, blue, alpha, NULL);
180       }
181       else if (zoom) {
182          gl_write_zoomed_color_span( ctx, width, destx, dy, zspan,
183                                      red, green, blue, alpha, desty );
184       }
185       else {
186          gl_write_color_span( ctx, width, destx, dy, zspan,
187                               red, green, blue, alpha, GL_BITMAP );
188       }
189    }
190    UNDEFARRAY( zspan );
191    UNDEFARRAY( red );
192    UNDEFARRAY( green );
193    UNDEFARRAY( blue );
194    UNDEFARRAY( alpha );
195 }
196 
197 
198 
copy_ci_pixels(GLcontext * ctx,GLint srcx,GLint srcy,GLint width,GLint height,GLint destx,GLint desty)199 static void copy_ci_pixels( GLcontext* ctx,
200                             GLint srcx, GLint srcy, GLint width, GLint height,
201                             GLint destx, GLint desty )
202 {
203    GLdepth zspan[MAX_WIDTH];
204    GLuint indx[MAX_WIDTH];
205    GLint sy, dy, stepy;
206    GLint i, j;
207    GLboolean setbuffer, zoom;
208 
209    if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
210       zoom = GL_FALSE;
211    }
212    else {
213       zoom = GL_TRUE;
214    }
215 
216    /* Determine if copy should be bottom-to-top or top-to-bottom */
217    if (srcy<desty) {
218       /* top-down  max-to-min */
219       sy = srcy + height - 1;
220       dy = desty + height - 1;
221       stepy = -1;
222    }
223    else {
224       /* bottom-up  min-to-max */
225       sy = srcy;
226       dy = desty;
227       stepy = 1;
228    }
229 
230    if (ctx->Depth.Test) {
231       /* fill in array of z values */
232       GLint z = (GLint) (ctx->Current.RasterPos[2] * DEPTH_SCALE);
233       for (i=0;i<width;i++) {
234          zspan[i] = z;
235       }
236    }
237 
238    /* If read and draw buffer are different we must do buffer switching */
239    setbuffer = ctx->Pixel.ReadBuffer!=ctx->Color.DrawBuffer;
240 
241    for (j=0; j<height; j++, sy+=stepy, dy+=stepy) {
242       /* read */
243       if (setbuffer) {
244          (*ctx->Driver.SetBuffer)( ctx, ctx->Pixel.ReadBuffer );
245       }
246       gl_read_index_span( ctx, width, srcx, sy, indx );
247 
248       /* shift, offset */
249       if (ctx->Pixel.IndexShift || ctx->Pixel.IndexOffset) {
250          if (ctx->Pixel.IndexShift<0) {
251             for (i=0;i<width;i++) {
252                indx[i] = (indx[i] >> -ctx->Pixel.IndexShift)
253                          + ctx->Pixel.IndexOffset;
254             }
255          }
256          else {
257             for (i=0;i<width;i++) {
258                indx[i] = (indx[i] << ctx->Pixel.IndexShift)
259                          + ctx->Pixel.IndexOffset;
260             }
261          }
262       }
263 
264       /* mapping */
265       if (ctx->Pixel.MapColorFlag) {
266          for (i=0;i<width;i++) {
267             if (indx[i] < ctx->Pixel.MapItoIsize) {
268                indx[i] = ctx->Pixel.MapItoI[ indx[i] ];
269             }
270          }
271       }
272 
273       /* write */
274       if (setbuffer) {
275          (*ctx->Driver.SetBuffer)( ctx, ctx->Color.DrawBuffer );
276       }
277       if (zoom) {
278          gl_write_zoomed_index_span( ctx, width, destx, dy, zspan, indx, desty );
279       }
280       else {
281          gl_write_index_span( ctx, width, destx, dy, zspan, indx, GL_BITMAP );
282       }
283    }
284 }
285 
286 
287 
288 /*
289  * TODO: Optimize!!!!
290  */
copy_depth_pixels(GLcontext * ctx,GLint srcx,GLint srcy,GLint width,GLint height,GLint destx,GLint desty)291 static void copy_depth_pixels( GLcontext* ctx, GLint srcx, GLint srcy,
292                                GLint width, GLint height,
293                                GLint destx, GLint desty )
294 {
295    GLfloat depth[MAX_WIDTH];
296    GLdepth zspan[MAX_WIDTH];
297    GLuint indx[MAX_WIDTH];
298    GLubyte red[MAX_WIDTH], green[MAX_WIDTH];
299    GLubyte blue[MAX_WIDTH], alpha[MAX_WIDTH];
300    GLint sy, dy, stepy;
301    GLint i, j;
302    GLboolean zoom;
303 
304    if (!ctx->Buffer->Depth) {
305       gl_error( ctx, GL_INVALID_OPERATION, "glCopyPixels" );
306       return;
307    }
308 
309    if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
310       zoom = GL_FALSE;
311    }
312    else {
313       zoom = GL_TRUE;
314    }
315 
316    /* Determine if copy should be bottom-to-top or top-to-bottom */
317    if (srcy<desty) {
318       /* top-down  max-to-min */
319       sy = srcy + height - 1;
320       dy = desty + height - 1;
321       stepy = -1;
322    }
323    else {
324       /* bottom-up  min-to-max */
325       sy = srcy;
326       dy = desty;
327       stepy = 1;
328    }
329 
330    /* setup colors or indexes */
331    if (ctx->Visual->RGBAflag) {
332       GLubyte r, g, b, a;
333       r = ctx->Current.ByteColor[0];
334       g = ctx->Current.ByteColor[1];
335       b = ctx->Current.ByteColor[2];
336       a = ctx->Current.ByteColor[3];
337       MEMSET( red,   (int) r, width );
338       MEMSET( green, (int) g, width );
339       MEMSET( blue,  (int) b, width );
340       MEMSET( alpha, (int) a, width );
341    }
342    else {
343       for (i=0;i<width;i++) {
344          indx[i] = ctx->Current.Index;
345       }
346    }
347 
348    for (j=0; j<height; j++, sy+=stepy, dy+=stepy) {
349       /* read */
350       (*ctx->Driver.ReadDepthSpanFloat)( ctx, width, srcx, sy, depth );
351       /* scale, bias, clamp */
352       for (i=0;i<width;i++) {
353          GLfloat d = depth[i] * ctx->Pixel.DepthScale + ctx->Pixel.DepthBias;
354          zspan[i] = (GLint) (CLAMP( d, 0.0, 1.0 ) * DEPTH_SCALE);
355       }
356       /* write */
357       if (ctx->Visual->RGBAflag) {
358          if (zoom) {
359             gl_write_zoomed_color_span( ctx, width, destx, dy, zspan,
360                                         red, green, blue, alpha, desty );
361          }
362          else {
363             gl_write_color_span( ctx, width, destx, dy, zspan,
364                                  red, green, blue, alpha, GL_BITMAP );
365          }
366       }
367       else {
368          if (zoom) {
369             gl_write_zoomed_index_span( ctx, width, destx, dy,
370                                         zspan, indx, desty);
371          }
372          else {
373             gl_write_index_span( ctx, width, destx, dy,
374                                  zspan, indx, GL_BITMAP );
375          }
376       }
377    }
378 }
379 
380 
381 
copy_stencil_pixels(GLcontext * ctx,GLint srcx,GLint srcy,GLint width,GLint height,GLint destx,GLint desty)382 static void copy_stencil_pixels( GLcontext* ctx, GLint srcx, GLint srcy,
383                                  GLint width, GLint height,
384                                  GLint destx, GLint desty )
385 {
386    GLubyte stencil[MAX_WIDTH];
387    GLint sy, dy, stepy;
388    GLint i, j;
389    GLboolean zoom;
390 
391    if (!ctx->Buffer->Stencil) {
392       gl_error( ctx, GL_INVALID_OPERATION, "glCopyPixels" );
393       return;
394    }
395 
396    if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
397       zoom = GL_FALSE;
398    }
399    else {
400       zoom = GL_TRUE;
401    }
402 
403    /* Determine if copy should be bottom-to-top or top-to-bottom */
404    if (srcy<desty) {
405       /* top-down  max-to-min */
406       sy = srcy + height - 1;
407       dy = desty + height - 1;
408       stepy = -1;
409    }
410    else {
411       /* bottom-up  min-to-max */
412       sy = srcy;
413       dy = desty;
414       stepy = 1;
415    }
416 
417    for (j=0; j<height; j++, sy+=stepy, dy+=stepy) {
418       /* read */
419       gl_read_stencil_span( ctx, width, srcx, sy, stencil );
420       /* shift, offset */
421       if (ctx->Pixel.IndexShift<0) {
422          for (i=0;i<width;i++) {
423             stencil[i] = (stencil[i] >> -ctx->Pixel.IndexShift)
424                          + ctx->Pixel.IndexOffset;
425          }
426       }
427       else {
428          for (i=0;i<width;i++) {
429             stencil[i] = (stencil[i] << ctx->Pixel.IndexShift)
430 			 + ctx->Pixel.IndexOffset;
431          }
432       }
433       /* mapping */
434       if (ctx->Pixel.MapStencilFlag) {
435          for (i=0;i<width;i++) {
436             if ((GLint) stencil[i] < ctx->Pixel.MapStoSsize) {
437                stencil[i] = ctx->Pixel.MapStoS[ stencil[i] ];
438             }
439          }
440       }
441       /* write */
442       if (zoom) {
443          gl_write_zoomed_stencil_span( ctx, width, destx, dy, stencil, desty );
444       }
445       else {
446          gl_write_stencil_span( ctx, width, destx, dy, stencil );
447       }
448    }
449 }
450 
451 
452 
453 
gl_CopyPixels(GLcontext * ctx,GLint srcx,GLint srcy,GLsizei width,GLsizei height,GLenum type)454 void gl_CopyPixels( GLcontext* ctx, GLint srcx, GLint srcy, GLsizei width, GLsizei height,
455 		    GLenum type )
456 {
457    GLint destx, desty;
458 
459    if (INSIDE_BEGIN_END(ctx)) {
460       gl_error( ctx, GL_INVALID_OPERATION, "glCopyPixels" );
461       return;
462    }
463 
464    if (width<0 || height<0) {
465       gl_error( ctx, GL_INVALID_VALUE, "glCopyPixels" );
466       return;
467    }
468 
469    if (ctx->NewState) {
470       gl_update_state(ctx);
471    }
472 
473    if (ctx->RenderMode==GL_RENDER) {
474       /* Destination of copy: */
475       if (!ctx->Current.RasterPosValid) {
476 	 return;
477       }
478       destx = (GLint) (ctx->Current.RasterPos[0] + 0.5F);
479       desty = (GLint) (ctx->Current.RasterPos[1] + 0.5F);
480 
481       if (type==GL_COLOR && ctx->Visual->RGBAflag) {
482          copy_rgb_pixels( ctx, srcx, srcy, width, height, destx, desty );
483       }
484       else if (type==GL_COLOR && !ctx->Visual->RGBAflag) {
485          copy_ci_pixels( ctx, srcx, srcy, width, height, destx, desty );
486       }
487       else if (type==GL_DEPTH) {
488          copy_depth_pixels( ctx, srcx, srcy, width, height, destx, desty );
489       }
490       else if (type==GL_STENCIL) {
491          copy_stencil_pixels( ctx, srcx, srcy, width, height, destx, desty );
492       }
493       else {
494 	 gl_error( ctx, GL_INVALID_ENUM, "glCopyPixels" );
495       }
496    }
497    else if (ctx->RenderMode==GL_FEEDBACK) {
498       GLfloat color[4];
499       color[0] = ctx->Current.ByteColor[0] * ctx->Visual->InvRedScale;
500       color[1] = ctx->Current.ByteColor[1] * ctx->Visual->InvGreenScale;
501       color[2] = ctx->Current.ByteColor[2] * ctx->Visual->InvBlueScale;
502       color[3] = ctx->Current.ByteColor[3] * ctx->Visual->InvAlphaScale;
503       FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_COPY_PIXEL_TOKEN );
504       gl_feedback_vertex( ctx, ctx->Current.RasterPos[0],
505 			  ctx->Current.RasterPos[1],
506 			  ctx->Current.RasterPos[2],
507 			  ctx->Current.RasterPos[3],
508 			  color, ctx->Current.Index,
509 			  ctx->Current.TexCoord );
510    }
511    else if (ctx->RenderMode==GL_SELECT) {
512       gl_update_hitflag( ctx, ctx->Current.RasterPos[2] );
513    }
514 
515 }
516 
517 
518