source: trunk/src/opengl/mesa/copypix.c@ 3582

Last change on this file since 3582 was 2962, checked in by jeroen, 25 years ago

* empty log message *

File size: 15.5 KB
Line 
1/* $Id: copypix.c,v 1.2 2000-03-01 18:49:25 jeroen Exp $ */
2
3/*
4 * Mesa 3-D graphics library
5 * Version: 3.1
6 *
7 * Copyright (C) 1999 Brian Paul All Rights Reserved.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
26
27
28
29
30
31#ifdef PC_HEADER
32#include "all.h"
33#else
34#ifndef XFree86Server
35#include <string.h>
36#else
37#include "GL/xf86glx.h"
38#endif
39#include "types.h"
40#include "context.h"
41#include "copypix.h"
42#include "depth.h"
43#include "feedback.h"
44#include "macros.h"
45#include "mmath.h"
46#include "pixel.h"
47#include "span.h"
48#include "stencil.h"
49#include "zoom.h"
50#endif
51#ifdef __WIN32OS2__
52#include <malloc.h>
53#endif
54
55/*
56 * Determine if there's overlap in an image copy
57 */
58static GLboolean
59regions_overlap(int srcx, int srcy, int dstx, int dsty, int width, int height,
60 float zoomX, float zoomY)
61{
62 if ((srcx > dstx + (width * zoomX) + 1) || (srcx + width + 1 < dstx)) {
63 return GL_FALSE;
64 }
65 else if ((srcy < dsty) && (srcy + height < dsty + (height * zoomY))) {
66 return GL_FALSE;
67 }
68 else if ((srcy > dsty) && (srcy + height > dsty + (height * zoomY))) {
69 return GL_FALSE;
70 }
71 else {
72 return GL_TRUE;
73 }
74}
75
76
77
78
79static void copy_rgba_pixels( GLcontext* ctx,
80 GLint srcx, GLint srcy,
81 GLint width, GLint height,
82 GLint destx, GLint desty )
83{
84 GLdepth zspan[MAX_WIDTH];
85 GLubyte rgba[MAX_WIDTH][4];
86 GLubyte *prgba,*p;
87 GLboolean quick_draw;
88 GLint sy, dy, stepy;
89 GLint i, j;
90 GLboolean changeBuffer;
91 GLubyte *saveAlpha;
92 const GLboolean zoom = ctx->Pixel.ZoomX!=1.0F || ctx->Pixel.ZoomY!=1.0F;
93 GLboolean needbuffer;
94
95 /* Determine if copy should be done bottom-to-top or top-to-bottom */
96 if (srcy<desty) {
97 /* top-down max-to-min */
98 sy = srcy + height - 1;
99 dy = desty + height - 1;
100 stepy = -1;
101 }
102 else {
103 /* bottom-up min-to-max */
104 sy = srcy;
105 dy = desty;
106 stepy = 1;
107 }
108
109 needbuffer = regions_overlap(srcx, srcy, destx, desty, width, height,
110 ctx->Pixel.ZoomX, ctx->Pixel.ZoomY);
111
112 if (ctx->Depth.Test || ctx->Fog.Enabled) {
113 /* fill in array of z values */
114 GLint z = (GLint) (ctx->Current.RasterPos[2] * DEPTH_SCALE);
115 for (i=0;i<width;i++) {
116 zspan[i] = z;
117 }
118 }
119
120 if (ctx->RasterMask==0 && !zoom
121 && destx>=0 && destx+width<=ctx->Buffer->Width) {
122 quick_draw = GL_TRUE;
123 }
124 else {
125 quick_draw = GL_FALSE;
126 }
127
128 /* If read and draw buffer are different we must do buffer switching */
129 saveAlpha = ctx->Buffer->Alpha;
130 changeBuffer = ctx->Pixel.ReadBuffer != ctx->Color.DrawBuffer;
131
132 if (needbuffer) {
133 GLint ssy = sy;
134 prgba = (GLubyte *) MALLOC(width*height*sizeof(GLubyte)*4);
135 if (!prgba) {
136 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyPixels" );
137 return;
138 }
139 p = prgba;
140 if (changeBuffer) {
141 (*ctx->Driver.SetBuffer)( ctx, ctx->Pixel.DriverReadBuffer );
142 if (ctx->Pixel.DriverReadBuffer == GL_FRONT_LEFT)
143 ctx->Buffer->Alpha = ctx->Buffer->FrontLeftAlpha;
144 else if (ctx->Pixel.DriverReadBuffer == GL_BACK_LEFT)
145 ctx->Buffer->Alpha = ctx->Buffer->BackLeftAlpha;
146 else if (ctx->Pixel.DriverReadBuffer == GL_FRONT_RIGHT)
147 ctx->Buffer->Alpha = ctx->Buffer->FrontRightAlpha;
148 else
149 ctx->Buffer->Alpha = ctx->Buffer->BackRightAlpha;
150 }
151 for (j=0; j<height; j++, ssy+=stepy) {
152 gl_read_rgba_span( ctx, width, srcx, ssy,(GLubyte (*)[4]) p );
153 p += (width*sizeof(GLubyte)*4);
154 }
155 p = prgba;
156 }
157
158 for (j=0; j<height; j++, sy+=stepy, dy+=stepy) {
159 if (needbuffer) {
160 MEMCPY(rgba, p, width * sizeof(GLubyte) * 4);
161 p += (width * sizeof(GLubyte) * 4);
162 }
163 else {
164 if (changeBuffer) {
165 (*ctx->Driver.SetBuffer)( ctx, ctx->Pixel.DriverReadBuffer );
166 if (ctx->Pixel.DriverReadBuffer == GL_FRONT_LEFT)
167 ctx->Buffer->Alpha = ctx->Buffer->FrontLeftAlpha;
168 else if (ctx->Pixel.DriverReadBuffer == GL_BACK_LEFT)
169 ctx->Buffer->Alpha = ctx->Buffer->BackLeftAlpha;
170 else if (ctx->Pixel.DriverReadBuffer == GL_FRONT_RIGHT)
171 ctx->Buffer->Alpha = ctx->Buffer->FrontRightAlpha;
172 else
173 ctx->Buffer->Alpha = ctx->Buffer->BackRightAlpha;
174 }
175 gl_read_rgba_span( ctx, width, srcx, sy, rgba );
176 }
177 if (ctx->Pixel.ScaleOrBiasRGBA) {
178 gl_scale_and_bias_rgba( ctx, width, rgba );
179 }
180 if (ctx->Pixel.MapColorFlag) {
181 gl_map_rgba( ctx, width, rgba );
182 }
183 if (quick_draw && dy>=0 && dy<ctx->Buffer->Height) {
184 (*ctx->Driver.WriteRGBASpan)( ctx, width, destx, dy,
185 (const GLubyte (*)[4])rgba, NULL );
186
187 }
188 else if (zoom) {
189 gl_write_zoomed_rgba_span( ctx, width, destx, dy, zspan,
190 (const GLubyte (*)[4])rgba, desty);
191 }
192 else {
193 gl_write_rgba_span( ctx, width, destx, dy, zspan, rgba, GL_BITMAP );
194 }
195 }
196
197 if (needbuffer)
198 FREE(prgba);
199
200 /* Restore current alpha buffer pointer */
201 ctx->Buffer->Alpha = saveAlpha;
202 if (changeBuffer)
203 (*ctx->Driver.SetBuffer)( ctx, ctx->Color.DriverDrawBuffer );
204}
205
206
207static void copy_ci_pixels( GLcontext* ctx,
208 GLint srcx, GLint srcy, GLint width, GLint height,
209 GLint destx, GLint desty )
210{
211 GLdepth zspan[MAX_WIDTH];
212 GLuint *pci,*p;
213 GLint sy, dy, stepy;
214 GLint i, j;
215 GLboolean changeBuffer;
216 const GLboolean zoom = ctx->Pixel.ZoomX!=1.0F || ctx->Pixel.ZoomY!=1.0F;
217 const GLboolean shift_or_offset = ctx->Pixel.IndexShift || ctx->Pixel.IndexOffset;
218 GLboolean needbuffer;
219
220 /* Determine if copy should be bottom-to-top or top-to-bottom */
221 if (srcy<desty) {
222 /* top-down max-to-min */
223 sy = srcy + height - 1;
224 dy = desty + height - 1;
225 stepy = -1;
226 }
227 else {
228 /* bottom-up min-to-max */
229 sy = srcy;
230 dy = desty;
231 stepy = 1;
232 }
233
234 needbuffer = regions_overlap(srcx, srcy, destx, desty, width, height,
235 ctx->Pixel.ZoomX, ctx->Pixel.ZoomY);
236
237 if (ctx->Depth.Test || ctx->Fog.Enabled) {
238 /* fill in array of z values */
239 GLint z = (GLint) (ctx->Current.RasterPos[2] * DEPTH_SCALE);
240 for (i=0;i<width;i++) {
241 zspan[i] = z;
242 }
243 }
244
245 /* If read and draw buffer are different we must do buffer switching */
246 changeBuffer = ctx->Pixel.ReadBuffer!=ctx->Color.DrawBuffer;
247
248 if (needbuffer) {
249 GLint ssy = sy;
250 pci = (GLuint *) MALLOC(width * height * sizeof(GLuint));
251 if (!pci) {
252 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyPixels" );
253 return;
254 }
255 p = pci;
256 if (changeBuffer) {
257 (*ctx->Driver.SetBuffer)( ctx, ctx->Pixel.DriverReadBuffer );
258 }
259 for (j=0; j<height; j++, ssy+=stepy) {
260 gl_read_index_span( ctx, width, srcx, ssy, p );
261 p += width;
262 }
263 p = pci;
264 }
265
266 for (j=0; j<height; j++, sy+=stepy, dy+=stepy) {
267 GLuint indexes[MAX_WIDTH];
268 if (needbuffer) {
269 MEMCPY(indexes, p, width * sizeof(GLuint));
270 p += width;
271 }
272 else {
273 if (changeBuffer) {
274 (*ctx->Driver.SetBuffer)( ctx, ctx->Pixel.DriverReadBuffer );
275 }
276 gl_read_index_span( ctx, width, srcx, sy, indexes );
277 }
278
279 if (shift_or_offset) {
280 gl_shift_and_offset_ci( ctx, width, indexes );
281 }
282 if (ctx->Pixel.MapColorFlag) {
283 gl_map_ci( ctx, width, indexes );
284 }
285
286 if (changeBuffer) {
287 (*ctx->Driver.SetBuffer)( ctx, ctx->Color.DrawBuffer );
288 }
289 if (zoom) {
290 gl_write_zoomed_index_span( ctx, width, destx, dy, zspan, indexes, desty );
291 }
292 else {
293 gl_write_index_span( ctx, width, destx, dy, zspan, indexes, GL_BITMAP );
294 }
295 }
296
297 if (needbuffer)
298 FREE(pci);
299
300 if (changeBuffer)
301 (*ctx->Driver.SetBuffer)( ctx, ctx->Color.DriverDrawBuffer );
302}
303
304
305
306/*
307 * TODO: Optimize!!!!
308 */
309static void copy_depth_pixels( GLcontext* ctx, GLint srcx, GLint srcy,
310 GLint width, GLint height,
311 GLint destx, GLint desty )
312{
313 GLfloat depth[MAX_WIDTH];
314 GLdepth zspan[MAX_WIDTH];
315 GLfloat *p,*pdepth;
316 GLuint indexes[MAX_WIDTH];
317 GLubyte rgba[MAX_WIDTH][4];
318 GLint sy, dy, stepy;
319 GLint i, j;
320 const GLboolean zoom = ctx->Pixel.ZoomX!=1.0F || ctx->Pixel.ZoomY!=1.0F;
321 GLboolean needbuffer;
322
323 if (!ctx->Buffer->Depth) {
324 gl_error( ctx, GL_INVALID_OPERATION, "glCopyPixels" );
325 return;
326 }
327
328 /* Determine if copy should be bottom-to-top or top-to-bottom */
329 if (srcy<desty) {
330 /* top-down max-to-min */
331 sy = srcy + height - 1;
332 dy = desty + height - 1;
333 stepy = -1;
334 }
335 else {
336 /* bottom-up min-to-max */
337 sy = srcy;
338 dy = desty;
339 stepy = 1;
340 }
341
342
343 needbuffer = regions_overlap(srcx, srcy, destx, desty, width, height,
344 ctx->Pixel.ZoomX, ctx->Pixel.ZoomY);
345
346 /* setup colors or indexes */
347 if (ctx->Visual->RGBAflag) {
348 GLuint *rgba32 = (GLuint *) rgba;
349 GLuint color = *(GLuint*)( ctx->Current.ByteColor );
350 for (i=0; i<width; i++) {
351 rgba32[i] = color;
352 }
353 }
354 else {
355 for (i=0;i<width;i++) {
356 indexes[i] = ctx->Current.Index;
357 }
358 }
359
360 if (needbuffer) {
361 GLint ssy = sy;
362 pdepth = (GLfloat *) MALLOC(width * height * sizeof(GLfloat));
363 if (!pdepth) {
364 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyPixels" );
365 return;
366 }
367 p = pdepth;
368 for (j=0; j<height; j++, ssy+=stepy) {
369 (*ctx->Driver.ReadDepthSpanFloat)( ctx, width, srcx, ssy, p );
370 p += width;
371 }
372 p = pdepth;
373 }
374
375 for (j=0; j<height; j++, sy+=stepy, dy+=stepy) {
376 if (needbuffer) {
377 MEMCPY(depth, p, width * sizeof(GLfloat));
378 p += width;
379 }
380 else {
381 (*ctx->Driver.ReadDepthSpanFloat)( ctx, width, srcx, sy, depth );
382 }
383
384 for (i=0;i<width;i++) {
385 GLfloat d = depth[i] * ctx->Pixel.DepthScale + ctx->Pixel.DepthBias;
386 zspan[i] = (GLint) (CLAMP( d, 0.0F, 1.0F ) * DEPTH_SCALE);
387 }
388
389 if (ctx->Visual->RGBAflag) {
390 if (zoom) {
391 gl_write_zoomed_rgba_span( ctx, width, destx, dy, zspan,
392 (const GLubyte (*)[4])rgba, desty );
393 }
394 else {
395 gl_write_rgba_span( ctx, width, destx, dy, zspan, rgba, GL_BITMAP);
396 }
397 }
398 else {
399 if (zoom) {
400 gl_write_zoomed_index_span( ctx, width, destx, dy,
401 zspan, indexes, desty );
402 }
403 else {
404 gl_write_index_span( ctx, width, destx, dy,
405 zspan, indexes, GL_BITMAP );
406 }
407 }
408 }
409
410 if (needbuffer)
411 FREE(pdepth);
412}
413
414
415
416static void copy_stencil_pixels( GLcontext* ctx, GLint srcx, GLint srcy,
417 GLint width, GLint height,
418 GLint destx, GLint desty )
419{
420 GLint sy, dy, stepy;
421 GLint j;
422 GLstencil *p,*psten;
423 const GLboolean zoom = (ctx->Pixel.ZoomX!=1.0F || ctx->Pixel.ZoomY!=1.0F);
424 const GLboolean shift_or_offset = ctx->Pixel.IndexShift!=0 || ctx->Pixel.IndexOffset!=0;
425 GLboolean needbuffer;
426
427 if (!ctx->Buffer->Stencil) {
428 gl_error( ctx, GL_INVALID_OPERATION, "glCopyPixels" );
429 return;
430 }
431
432 /* Determine if copy should be bottom-to-top or top-to-bottom */
433 if (srcy<desty) {
434 /* top-down max-to-min */
435 sy = srcy + height - 1;
436 dy = desty + height - 1;
437 stepy = -1;
438 }
439 else {
440 /* bottom-up min-to-max */
441 sy = srcy;
442 dy = desty;
443 stepy = 1;
444 }
445
446 needbuffer = regions_overlap(srcx, srcy, destx, desty, width, height,
447 ctx->Pixel.ZoomX, ctx->Pixel.ZoomY);
448
449 if (needbuffer) {
450 GLint ssy = sy;
451 psten = (GLstencil *) MALLOC(width * height * sizeof(GLstencil));
452 if (!psten) {
453 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyPixels" );
454 return;
455 }
456 p = psten;
457 for (j=0; j<height; j++, ssy+=stepy) {
458 gl_read_stencil_span( ctx, width, srcx, ssy, p );
459 p += width;
460 }
461 p = psten;
462 }
463
464 for (j=0; j<height; j++, sy+=stepy, dy+=stepy) {
465 GLstencil stencil[MAX_WIDTH];
466
467 if (needbuffer) {
468 MEMCPY(stencil, p, width * sizeof(GLstencil));
469 p += width;
470 }
471 else {
472 gl_read_stencil_span( ctx, width, srcx, sy, stencil );
473 }
474
475 if (shift_or_offset) {
476 gl_shift_and_offset_stencil( ctx, width, stencil );
477 }
478 if (ctx->Pixel.MapStencilFlag) {
479 gl_map_stencil( ctx, width, stencil );
480 }
481
482 if (zoom) {
483 gl_write_zoomed_stencil_span( ctx, width, destx, dy, stencil, desty );
484 }
485 else {
486 gl_write_stencil_span( ctx, width, destx, dy, stencil );
487 }
488 }
489
490 if (needbuffer)
491 FREE(psten);
492}
493
494
495
496
497void gl_CopyPixels( GLcontext* ctx, GLint srcx, GLint srcy,
498 GLsizei width, GLsizei height, GLenum type )
499{
500 GLint destx, desty;
501
502 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyPixels");
503
504 if (width<0 || height<0) {
505 gl_error( ctx, GL_INVALID_VALUE, "glCopyPixels" );
506 return;
507 }
508
509 if (ctx->NewState) {
510 gl_update_state(ctx);
511 }
512
513 if (ctx->RenderMode==GL_RENDER) {
514 /* Destination of copy: */
515 if (!ctx->Current.RasterPosValid) {
516 return;
517 }
518 destx = (GLint) (ctx->Current.RasterPos[0] + 0.5F);
519 desty = (GLint) (ctx->Current.RasterPos[1] + 0.5F);
520
521 if (type==GL_COLOR && ctx->Visual->RGBAflag) {
522 copy_rgba_pixels( ctx, srcx, srcy, width, height, destx, desty );
523 }
524 else if (type==GL_COLOR && !ctx->Visual->RGBAflag) {
525 copy_ci_pixels( ctx, srcx, srcy, width, height, destx, desty );
526 }
527 else if (type==GL_DEPTH) {
528 copy_depth_pixels( ctx, srcx, srcy, width, height, destx, desty );
529 }
530 else if (type==GL_STENCIL) {
531 copy_stencil_pixels( ctx, srcx, srcy, width, height, destx, desty );
532 }
533 else {
534 gl_error( ctx, GL_INVALID_ENUM, "glCopyPixels" );
535 }
536 }
537 else if (ctx->RenderMode==GL_FEEDBACK) {
538 GLfloat color[4];
539 UBYTE_RGBA_TO_FLOAT_RGBA(color, ctx->Current.ByteColor );
540 FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_COPY_PIXEL_TOKEN );
541 gl_feedback_vertex( ctx, ctx->Current.RasterPos,
542 color, ctx->Current.Index,
543 ctx->Current.Texcoord[0] );
544 }
545 else if (ctx->RenderMode==GL_SELECT) {
546 gl_update_hitflag( ctx, ctx->Current.RasterPos[2] );
547 }
548
549}
Note: See TracBrowser for help on using the repository browser.