blob: 49321a94593755137b880c3be5f95a6dd92aec9a [file] [log] [blame]
Brian Pauled30dfa2000-03-03 17:47:39 +00001/* $Id: drawpix.c,v 1.14 2000/03/03 17:54:56 brianp Exp $ */
jtgafb833d1999-08-19 00:55:39 +00002
3/*
4 * Mesa 3-D graphics library
Brian Paulfbd8f211999-11-11 01:22:25 +00005 * Version: 3.3
jtgafb833d1999-08-19 00:55:39 +00006 *
Brian Paulbab8f792000-02-08 23:42:14 +00007 * Copyright (C) 1999-2000 Brian Paul All Rights Reserved.
jtgafb833d1999-08-19 00:55:39 +00008 *
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
jtgafb833d1999-08-19 00:55:39 +000028#ifdef PC_HEADER
29#include "all.h"
30#else
Brian Paulfbd8f211999-11-11 01:22:25 +000031#include "glheader.h"
jtgafb833d1999-08-19 00:55:39 +000032#include "context.h"
33#include "drawpix.h"
34#include "feedback.h"
35#include "image.h"
36#include "macros.h"
Brian Pauled30dfa2000-03-03 17:47:39 +000037#include "mem.h"
jtgafb833d1999-08-19 00:55:39 +000038#include "mmath.h"
39#include "pixel.h"
40#include "span.h"
Brian Paulea39f042000-02-02 19:17:57 +000041#include "state.h"
jtgafb833d1999-08-19 00:55:39 +000042#include "stencil.h"
43#include "types.h"
44#include "zoom.h"
jtgafb833d1999-08-19 00:55:39 +000045#endif
46
47
48
jtgafb833d1999-08-19 00:55:39 +000049/*
Brian Paul4e176ff1999-11-22 22:21:38 +000050 * Given the dest position, size and skipPixels and skipRows values
51 * for a glDrawPixels command, perform clipping of the image bounds
52 * so the result lies withing the context's buffer bounds.
53 * Return: GL_TRUE if image is ready for drawing
54 * GL_FALSE if image was completely clipped away (draw nothing)
55 */
56GLboolean
57_mesa_clip_pixelrect(const GLcontext *ctx,
58 GLint *destX, GLint *destY,
59 GLsizei *width, GLsizei *height,
60 GLint *skipPixels, GLint *skipRows)
61{
Brian Paul3f02f901999-11-24 18:48:30 +000062 const GLframebuffer *buffer = ctx->DrawBuffer;
63
Brian Paul4e176ff1999-11-22 22:21:38 +000064 /* left clipping */
Brian Paul3f02f901999-11-24 18:48:30 +000065 if (*destX < buffer->Xmin) {
66 *skipPixels += (buffer->Xmin - *destX);
67 *width -= (buffer->Xmin - *destX);
68 *destX = buffer->Xmin;
Brian Paul4e176ff1999-11-22 22:21:38 +000069 }
70 /* right clipping */
Brian Paul3f02f901999-11-24 18:48:30 +000071 if (*destX + *width > buffer->Xmax)
72 *width -= (*destX + *width - buffer->Xmax - 1);
Brian Paul4e176ff1999-11-22 22:21:38 +000073
74 if (*width <= 0)
75 return GL_FALSE;
76
77 /* bottom clipping */
Brian Paul3f02f901999-11-24 18:48:30 +000078 if (*destY < buffer->Ymin) {
79 *skipRows += (buffer->Ymin - *destY);
80 *height -= (buffer->Ymin - *destY);
81 *destY = buffer->Ymin;
Brian Paul4e176ff1999-11-22 22:21:38 +000082 }
83 /* top clipping */
Brian Paul3f02f901999-11-24 18:48:30 +000084 if (*destY + *height > buffer->Ymax)
85 *height -= (*destY + *height - buffer->Ymax - 1);
Brian Paul4e176ff1999-11-22 22:21:38 +000086
87 if (*height <= 0)
88 return GL_TRUE;
89
90 return GL_TRUE;
91}
92
93
94
95/*
Brian Paulfbd8f211999-11-11 01:22:25 +000096 * Try to do a fast and simple RGB(a) glDrawPixels.
jtgafb833d1999-08-19 00:55:39 +000097 * Return: GL_TRUE if success, GL_FALSE if slow path must be used instead
98 */
Brian Paulfbd8f211999-11-11 01:22:25 +000099static GLboolean
100simple_DrawPixels( GLcontext *ctx, GLint x, GLint y,
101 GLsizei width, GLsizei height, GLenum format, GLenum type,
102 const GLvoid *pixels )
jtgafb833d1999-08-19 00:55:39 +0000103{
Brian Paulfbd8f211999-11-11 01:22:25 +0000104 const struct gl_pixelstore_attrib *unpack = &ctx->Unpack;
jtgafb833d1999-08-19 00:55:39 +0000105 GLubyte rgb[MAX_WIDTH][3];
106 GLubyte rgba[MAX_WIDTH][4];
107
108 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH_WITH_RETVAL(ctx, "glDrawPixels",
109 GL_FALSE);
110
111
112 if (!ctx->Current.RasterPosValid) {
113 /* no-op */
114 return GL_TRUE;
115 }
116
117 if (ctx->NewState) {
118 gl_update_state(ctx);
119 }
120
jtgafb833d1999-08-19 00:55:39 +0000121 if ((ctx->RasterMask&(~(SCISSOR_BIT|WINCLIP_BIT)))==0
122 && ctx->Pixel.RedBias==0.0 && ctx->Pixel.RedScale==1.0
123 && ctx->Pixel.GreenBias==0.0 && ctx->Pixel.GreenScale==1.0
124 && ctx->Pixel.BlueBias==0.0 && ctx->Pixel.BlueScale==1.0
125 && ctx->Pixel.AlphaBias==0.0 && ctx->Pixel.AlphaScale==1.0
126 && ctx->Pixel.IndexShift==0 && ctx->Pixel.IndexOffset==0
127 && ctx->Pixel.MapColorFlag==0
128 && unpack->Alignment==1
129 && !unpack->SwapBytes
130 && !unpack->LsbFirst) {
131
Brian Paulfbd8f211999-11-11 01:22:25 +0000132 GLint destX = x;
133 GLint destY = y;
jtgafb833d1999-08-19 00:55:39 +0000134 GLint drawWidth = width; /* actual width drawn */
135 GLint drawHeight = height; /* actual height drawn */
136 GLint skipPixels = unpack->SkipPixels;
137 GLint skipRows = unpack->SkipRows;
138 GLint rowLength;
139 GLdepth zSpan[MAX_WIDTH]; /* only used when zooming */
140 GLint zoomY0;
141
142 if (unpack->RowLength > 0)
143 rowLength = unpack->RowLength;
144 else
145 rowLength = width;
146
147 /* If we're not using pixel zoom then do all clipping calculations
148 * now. Otherwise, we'll let the gl_write_zoomed_*_span() functions
149 * handle the clipping.
150 */
151 if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
152 /* horizontal clipping */
Brian Paul3f02f901999-11-24 18:48:30 +0000153 if (destX < ctx->DrawBuffer->Xmin) {
154 skipPixels += (ctx->DrawBuffer->Xmin - destX);
155 drawWidth -= (ctx->DrawBuffer->Xmin - destX);
156 destX = ctx->DrawBuffer->Xmin;
jtgafb833d1999-08-19 00:55:39 +0000157 }
Brian Paul3f02f901999-11-24 18:48:30 +0000158 if (destX + drawWidth > ctx->DrawBuffer->Xmax)
159 drawWidth -= (destX + drawWidth - ctx->DrawBuffer->Xmax - 1);
jtgafb833d1999-08-19 00:55:39 +0000160 if (drawWidth <= 0)
161 return GL_TRUE;
162
163 /* vertical clipping */
Brian Paul3f02f901999-11-24 18:48:30 +0000164 if (destY < ctx->DrawBuffer->Ymin) {
165 skipRows += (ctx->DrawBuffer->Ymin - destY);
166 drawHeight -= (ctx->DrawBuffer->Ymin - destY);
167 destY = ctx->DrawBuffer->Ymin;
jtgafb833d1999-08-19 00:55:39 +0000168 }
Brian Paul3f02f901999-11-24 18:48:30 +0000169 if (destY + drawHeight > ctx->DrawBuffer->Ymax)
170 drawHeight -= (destY + drawHeight - ctx->DrawBuffer->Ymax - 1);
jtgafb833d1999-08-19 00:55:39 +0000171 if (drawHeight <= 0)
172 return GL_TRUE;
Brian Paul4b7526d1999-11-18 15:44:37 +0000173
174 zoomY0 = 0; /* not used - silence compiler warning */
jtgafb833d1999-08-19 00:55:39 +0000175 }
176 else {
177 /* setup array of fragment Z value to pass to zoom function */
Brian Pauled30dfa2000-03-03 17:47:39 +0000178 GLdepth z = (GLdepth) (ctx->Current.RasterPos[2] * ctx->Visual->DepthMaxF);
jtgafb833d1999-08-19 00:55:39 +0000179 GLint i;
180 assert(drawWidth < MAX_WIDTH);
181 for (i=0; i<drawWidth; i++)
182 zSpan[i] = z;
183
184 /* save Y value of first row */
185 zoomY0 = (GLint) (ctx->Current.RasterPos[1] + 0.5F);
186 }
187
188
189 /*
190 * Ready to draw!
191 * The window region at (destX, destY) of size (drawWidth, drawHeight)
192 * will be written to.
193 * We'll take pixel data from buffer pointed to by "pixels" but we'll
194 * skip "skipRows" rows and skip "skipPixels" pixels/row.
195 */
196
197 if (format==GL_RGBA && type==GL_UNSIGNED_BYTE) {
198 if (ctx->Visual->RGBAflag) {
199 GLubyte *src = (GLubyte *) pixels
200 + (skipRows * rowLength + skipPixels) * 4;
201 if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
202 /* no zooming */
203 GLint row;
204 for (row=0; row<drawHeight; row++) {
205 (*ctx->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY,
206 (void *) src, NULL);
207 src += rowLength * 4;
208 destY++;
209 }
210 }
211 else {
212 /* with zooming */
213 GLint row;
214 for (row=0; row<drawHeight; row++) {
215 gl_write_zoomed_rgba_span(ctx, drawWidth, destX, destY,
216 zSpan, (void *) src, zoomY0);
217 src += rowLength * 4;
218 destY++;
219 }
220 }
221 }
222 return GL_TRUE;
223 }
224 else if (format==GL_RGB && type==GL_UNSIGNED_BYTE) {
225 if (ctx->Visual->RGBAflag) {
226 GLubyte *src = (GLubyte *) pixels
227 + (skipRows * rowLength + skipPixels) * 3;
228 if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
229 GLint row;
230 for (row=0; row<drawHeight; row++) {
231 (*ctx->Driver.WriteRGBSpan)(ctx, drawWidth, destX, destY,
232 (void *) src, NULL);
233 src += rowLength * 3;
234 destY++;
235 }
236 }
237 else {
238 /* with zooming */
239 GLint row;
240 for (row=0; row<drawHeight; row++) {
241 gl_write_zoomed_rgb_span(ctx, drawWidth, destX, destY,
242 zSpan, (void *) src, zoomY0);
243 src += rowLength * 3;
244 destY++;
245 }
246 }
247 }
248 return GL_TRUE;
249 }
250 else if (format==GL_LUMINANCE && type==GL_UNSIGNED_BYTE) {
251 if (ctx->Visual->RGBAflag) {
252 GLubyte *src = (GLubyte *) pixels
253 + (skipRows * rowLength + skipPixels);
254 if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
255 /* no zooming */
256 GLint row;
257 assert(drawWidth < MAX_WIDTH);
258 for (row=0; row<drawHeight; row++) {
259 GLint i;
260 for (i=0;i<drawWidth;i++) {
261 rgb[i][0] = src[i];
262 rgb[i][1] = src[i];
263 rgb[i][2] = src[i];
264 }
265 (*ctx->Driver.WriteRGBSpan)(ctx, drawWidth, destX, destY,
266 (void *) rgb, NULL);
267 src += rowLength;
268 destY++;
269 }
270 }
271 else {
272 /* with zooming */
273 GLint row;
274 assert(drawWidth < MAX_WIDTH);
275 for (row=0; row<drawHeight; row++) {
276 GLint i;
277 for (i=0;i<drawWidth;i++) {
278 rgb[i][0] = src[i];
279 rgb[i][1] = src[i];
280 rgb[i][2] = src[i];
281 }
282 gl_write_zoomed_rgb_span(ctx, drawWidth, destX, destY,
283 zSpan, (void *) rgb, zoomY0);
284 src += rowLength;
285 destY++;
286 }
287 }
288 }
289 return GL_TRUE;
290 }
291 else if (format==GL_LUMINANCE_ALPHA && type==GL_UNSIGNED_BYTE) {
292 if (ctx->Visual->RGBAflag) {
293 GLubyte *src = (GLubyte *) pixels
294 + (skipRows * rowLength + skipPixels)*2;
295 if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
296 /* no zooming */
297 GLint row;
298 assert(drawWidth < MAX_WIDTH);
299 for (row=0; row<drawHeight; row++) {
300 GLint i;
301 GLubyte *ptr = src;
302 for (i=0;i<drawWidth;i++) {
303 rgba[i][0] = *ptr;
304 rgba[i][1] = *ptr;
305 rgba[i][2] = *ptr++;
306 rgba[i][3] = *ptr++;
307 }
308 (*ctx->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY,
309 (void *) rgba, NULL);
310 src += rowLength*2;
311 destY++;
312 }
313 }
314 else {
315 /* with zooming */
316 GLint row;
317 assert(drawWidth < MAX_WIDTH);
318 for (row=0; row<drawHeight; row++) {
319 GLubyte *ptr = src;
320 GLint i;
321 for (i=0;i<drawWidth;i++) {
322 rgba[i][0] = *ptr;
323 rgba[i][1] = *ptr;
324 rgba[i][2] = *ptr++;
325 rgba[i][3] = *ptr++;
326 }
327 gl_write_zoomed_rgba_span(ctx, drawWidth, destX, destY,
328 zSpan, (void *) rgba, zoomY0);
329 src += rowLength*2;
330 destY++;
331 }
332 }
333 }
334 return GL_TRUE;
335 }
336 else if (format==GL_COLOR_INDEX && type==GL_UNSIGNED_BYTE) {
337 GLubyte *src = (GLubyte *) pixels + skipRows * rowLength + skipPixels;
338 if (ctx->Visual->RGBAflag) {
339 /* convert CI data to RGBA */
340 if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
341 /* no zooming */
342 GLint row;
343 for (row=0; row<drawHeight; row++) {
344 assert(drawWidth < MAX_WIDTH);
345 gl_map_ci8_to_rgba(ctx, drawWidth, src, rgba);
346 (*ctx->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY,
347 (const GLubyte (*)[4])rgba,
348 NULL);
349 src += rowLength;
350 destY++;
351 }
352 return GL_TRUE;
353 }
354 else {
355 /* with zooming */
356 GLint row;
357 for (row=0; row<drawHeight; row++) {
358 assert(drawWidth < MAX_WIDTH);
359 gl_map_ci8_to_rgba(ctx, drawWidth, src, rgba);
360 gl_write_zoomed_rgba_span(ctx, drawWidth, destX, destY,
361 zSpan, (void *) rgba, zoomY0);
362 src += rowLength;
363 destY++;
364 }
365 return GL_TRUE;
366 }
367 }
368 else {
369 /* write CI data to CI frame buffer */
370 GLint row;
371 if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
372 /* no zooming */
373 for (row=0; row<drawHeight; row++) {
374 (*ctx->Driver.WriteCI8Span)(ctx, drawWidth, destX, destY,
375 src, NULL);
376 src += rowLength;
377 destY++;
378 }
379 return GL_TRUE;
380 }
381 else {
382 /* with zooming */
383 return GL_FALSE;
384 }
385 }
386 }
387 else {
388 /* can't handle this pixel format and/or data type here */
389 return GL_FALSE;
390 }
391 }
Brian Paulfbd8f211999-11-11 01:22:25 +0000392
393 /* can't do a simple draw, have to use slow path */
394 return GL_FALSE;
jtgafb833d1999-08-19 00:55:39 +0000395}
396
397
398
399/*
400 * Do glDrawPixels of index pixels.
401 */
Brian Paulfbd8f211999-11-11 01:22:25 +0000402static void
403draw_index_pixels( GLcontext *ctx, GLint x, GLint y,
404 GLsizei width, GLsizei height,
405 GLenum type, const GLvoid *pixels )
jtgafb833d1999-08-19 00:55:39 +0000406{
jtgafb833d1999-08-19 00:55:39 +0000407 const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
Brian Paulfbd8f211999-11-11 01:22:25 +0000408 const GLint desty = y;
409 GLint row, drawWidth;
410 GLdepth zspan[MAX_WIDTH];
jtgafb833d1999-08-19 00:55:39 +0000411
Brian Paulfbd8f211999-11-11 01:22:25 +0000412 drawWidth = (width > MAX_WIDTH) ? MAX_WIDTH : width;
jtgafb833d1999-08-19 00:55:39 +0000413
414 /* Fragment depth values */
Brian Paul7110c371999-11-26 16:27:05 +0000415 if (ctx->Depth.Test || ctx->Fog.Enabled) {
Brian Pauled30dfa2000-03-03 17:47:39 +0000416 GLdepth zval = (GLdepth) (ctx->Current.RasterPos[2] * ctx->Visual->DepthMaxF);
Brian Paulfbd8f211999-11-11 01:22:25 +0000417 GLint i;
418 for (i = 0; i < drawWidth; i++) {
jtgafb833d1999-08-19 00:55:39 +0000419 zspan[i] = zval;
420 }
421 }
422
Brian Paulfbd8f211999-11-11 01:22:25 +0000423 /*
424 * General solution
425 */
426 for (row = 0; row < height; row++, y++) {
427 GLuint indexes[MAX_WIDTH];
428 const GLvoid *source = gl_pixel_addr_in_image(&ctx->Unpack,
429 pixels, width, height, GL_COLOR_INDEX, type, 0, row, 0);
430 _mesa_unpack_index_span(ctx, drawWidth, GL_UNSIGNED_INT, indexes,
431 type, source, &ctx->Unpack, GL_TRUE);
432 if (zoom) {
433 gl_write_zoomed_index_span(ctx, drawWidth, x, y, zspan, indexes, desty);
jtgafb833d1999-08-19 00:55:39 +0000434 }
435 else {
Brian Paulfbd8f211999-11-11 01:22:25 +0000436 gl_write_index_span(ctx, drawWidth, x, y, zspan, indexes, GL_BITMAP);
jtgafb833d1999-08-19 00:55:39 +0000437 }
438 }
jtgafb833d1999-08-19 00:55:39 +0000439}
440
441
442
443/*
444 * Do glDrawPixels of stencil image. The image datatype may either
445 * be GLubyte or GLbitmap.
446 */
Brian Paulfbd8f211999-11-11 01:22:25 +0000447static void
448draw_stencil_pixels( GLcontext *ctx, GLint x, GLint y,
449 GLsizei width, GLsizei height,
450 GLenum type, const GLvoid *pixels )
jtgafb833d1999-08-19 00:55:39 +0000451{
jtgafb833d1999-08-19 00:55:39 +0000452 const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
Brian Paulfbd8f211999-11-11 01:22:25 +0000453 const GLint desty = y;
454 GLint row, drawWidth;
jtgafb833d1999-08-19 00:55:39 +0000455
Brian Paulfbd8f211999-11-11 01:22:25 +0000456 if (type != GL_BYTE &&
457 type != GL_UNSIGNED_BYTE &&
458 type != GL_SHORT &&
459 type != GL_UNSIGNED_SHORT &&
460 type != GL_INT &&
461 type != GL_UNSIGNED_INT &&
462 type != GL_FLOAT &&
463 type != GL_BITMAP) {
464 gl_error( ctx, GL_INVALID_ENUM, "glDrawPixels(stencil type)");
Brian Paulbc41b081999-10-19 20:33:57 +0000465 return;
466 }
467
Brian Paulfbd8f211999-11-11 01:22:25 +0000468 drawWidth = (width > MAX_WIDTH) ? MAX_WIDTH : width;
jtgafb833d1999-08-19 00:55:39 +0000469
Brian Paulfbd8f211999-11-11 01:22:25 +0000470 for (row = 0; row < height; row++, y++) {
471 GLstencil values[MAX_WIDTH];
472 GLenum destType = (sizeof(GLstencil) == sizeof(GLubyte))
473 ? GL_UNSIGNED_BYTE : GL_UNSIGNED_SHORT;
474 const GLvoid *source = gl_pixel_addr_in_image(&ctx->Unpack,
475 pixels, width, height, GL_COLOR_INDEX, type, 0, row, 0);
476 _mesa_unpack_index_span(ctx, drawWidth, destType, values,
477 type, source, &ctx->Unpack, GL_TRUE);
jtgafb833d1999-08-19 00:55:39 +0000478
jtgafb833d1999-08-19 00:55:39 +0000479 if (zoom) {
Brian Paulfbd8f211999-11-11 01:22:25 +0000480 gl_write_zoomed_stencil_span( ctx, (GLuint) drawWidth, x, y,
481 values, desty );
jtgafb833d1999-08-19 00:55:39 +0000482 }
483 else {
Brian Paulfbd8f211999-11-11 01:22:25 +0000484 gl_write_stencil_span( ctx, (GLuint) drawWidth, x, y, values );
jtgafb833d1999-08-19 00:55:39 +0000485 }
486 }
487}
488
489
490
491/*
492 * Do a glDrawPixels of depth values.
493 */
Brian Paulfbd8f211999-11-11 01:22:25 +0000494static void
495draw_depth_pixels( GLcontext *ctx, GLint x, GLint y,
496 GLsizei width, GLsizei height,
497 GLenum type, const GLvoid *pixels )
jtgafb833d1999-08-19 00:55:39 +0000498{
Brian Paulfbd8f211999-11-11 01:22:25 +0000499 const GLboolean bias_or_scale = ctx->Pixel.DepthBias!=0.0 || ctx->Pixel.DepthScale!=1.0;
500 const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
jtgafb833d1999-08-19 00:55:39 +0000501 const GLint desty = y;
502 GLubyte rgba[MAX_WIDTH][4];
503 GLuint ispan[MAX_WIDTH];
Brian Paulfbd8f211999-11-11 01:22:25 +0000504 GLint drawWidth = (width > MAX_WIDTH) ? MAX_WIDTH : width;
jtgafb833d1999-08-19 00:55:39 +0000505
Brian Paulfbd8f211999-11-11 01:22:25 +0000506 if (type != GL_UNSIGNED_BYTE
507 && type != GL_UNSIGNED_BYTE
508 && type != GL_UNSIGNED_SHORT
509 && type != GL_UNSIGNED_SHORT
510 && type != GL_UNSIGNED_INT
511 && type != GL_UNSIGNED_INT
512 && type != GL_FLOAT) {
513 gl_error(ctx, GL_INVALID_ENUM, "glDrawPixels(type)");
514 return;
515 }
jtgafb833d1999-08-19 00:55:39 +0000516
Brian Paulfbd8f211999-11-11 01:22:25 +0000517 /* Colors or indexes */
jtgafb833d1999-08-19 00:55:39 +0000518 if (ctx->Visual->RGBAflag) {
519 GLint r = (GLint) (ctx->Current.RasterColor[0] * 255.0F);
520 GLint g = (GLint) (ctx->Current.RasterColor[1] * 255.0F);
521 GLint b = (GLint) (ctx->Current.RasterColor[2] * 255.0F);
522 GLint a = (GLint) (ctx->Current.RasterColor[3] * 255.0F);
523 GLint i;
Brian Paulfbd8f211999-11-11 01:22:25 +0000524 for (i = 0; i < drawWidth; i++) {
jtgafb833d1999-08-19 00:55:39 +0000525 rgba[i][RCOMP] = r;
526 rgba[i][GCOMP] = g;
527 rgba[i][BCOMP] = b;
528 rgba[i][ACOMP] = a;
529 }
530 }
531 else {
532 GLint i;
Brian Paulfbd8f211999-11-11 01:22:25 +0000533 for (i = 0; i < drawWidth; i++) {
jtgafb833d1999-08-19 00:55:39 +0000534 ispan[i] = ctx->Current.RasterIndex;
535 }
536 }
537
Brian Paulfbd8f211999-11-11 01:22:25 +0000538 if (type==GL_UNSIGNED_SHORT && sizeof(GLdepth)==sizeof(GLushort)
jtgafb833d1999-08-19 00:55:39 +0000539 && !bias_or_scale && !zoom && ctx->Visual->RGBAflag) {
540 /* Special case: directly write 16-bit depth values */
Brian Paulfbd8f211999-11-11 01:22:25 +0000541 GLint row;
542 for (row = 0; row < height; row++, y++) {
Brian Pauled30dfa2000-03-03 17:47:39 +0000543 GLdepth zspan[MAX_WIDTH];
544 const GLushort *zptr = gl_pixel_addr_in_image(&ctx->Unpack,
Brian Paulfbd8f211999-11-11 01:22:25 +0000545 pixels, width, height, GL_DEPTH_COMPONENT, type, 0, row, 0);
Brian Pauled30dfa2000-03-03 17:47:39 +0000546 GLint i;
547 for (i = 0; i < width; i++)
548 zspan[i] = zptr[i];
549 gl_write_rgba_span( ctx, width, x, y, zspan, rgba, GL_BITMAP );
jtgafb833d1999-08-19 00:55:39 +0000550 }
551 }
Brian Pauled30dfa2000-03-03 17:47:39 +0000552 else if (type==GL_UNSIGNED_INT && ctx->Visual->DepthBits == 32
jtgafb833d1999-08-19 00:55:39 +0000553 && !bias_or_scale && !zoom && ctx->Visual->RGBAflag) {
554 /* Special case: directly write 32-bit depth values */
Brian Pauled30dfa2000-03-03 17:47:39 +0000555 GLint row;
Brian Paulfbd8f211999-11-11 01:22:25 +0000556 for (row = 0; row < height; row++, y++) {
Brian Pauled30dfa2000-03-03 17:47:39 +0000557 const GLuint *zptr = gl_pixel_addr_in_image(&ctx->Unpack,
Brian Paulfbd8f211999-11-11 01:22:25 +0000558 pixels, width, height, GL_DEPTH_COMPONENT, type, 0, row, 0);
Brian Pauled30dfa2000-03-03 17:47:39 +0000559 gl_write_rgba_span( ctx, width, x, y, zptr, rgba, GL_BITMAP );
jtgafb833d1999-08-19 00:55:39 +0000560 }
561 }
562 else {
Brian Paulfbd8f211999-11-11 01:22:25 +0000563 /* General case */
564 GLint row;
565 for (row = 0; row < height; row++, y++) {
jtgafb833d1999-08-19 00:55:39 +0000566 GLdepth zspan[MAX_WIDTH];
Brian Paulfbd8f211999-11-11 01:22:25 +0000567 const GLvoid *src = gl_pixel_addr_in_image(&ctx->Unpack,
568 pixels, width, height, GL_DEPTH_COMPONENT, type, 0, row, 0);
569 _mesa_unpack_depth_span( ctx, drawWidth, zspan, type, src,
570 &ctx->Unpack, GL_TRUE );
jtgafb833d1999-08-19 00:55:39 +0000571 if (ctx->Visual->RGBAflag) {
572 if (zoom) {
Brian Paulfbd8f211999-11-11 01:22:25 +0000573 gl_write_zoomed_rgba_span(ctx, width, x, y, zspan,
574 (const GLubyte (*)[4])rgba, desty);
jtgafb833d1999-08-19 00:55:39 +0000575 }
576 else {
Brian Paulfbd8f211999-11-11 01:22:25 +0000577 gl_write_rgba_span(ctx, width, x, y, zspan, rgba, GL_BITMAP);
jtgafb833d1999-08-19 00:55:39 +0000578 }
579 }
580 else {
581 if (zoom) {
Brian Paulfbd8f211999-11-11 01:22:25 +0000582 gl_write_zoomed_index_span(ctx, width, x, y, zspan,
583 ispan, GL_BITMAP);
jtgafb833d1999-08-19 00:55:39 +0000584 }
585 else {
Brian Paulfbd8f211999-11-11 01:22:25 +0000586 gl_write_index_span(ctx, width, x, y, zspan, ispan, GL_BITMAP);
jtgafb833d1999-08-19 00:55:39 +0000587 }
588 }
589
590 }
591 }
592}
593
594
jtgafb833d1999-08-19 00:55:39 +0000595/*
596 * Do glDrawPixels of RGBA pixels.
597 */
Brian Paulfbd8f211999-11-11 01:22:25 +0000598static void
599draw_rgba_pixels( GLcontext *ctx, GLint x, GLint y,
600 GLsizei width, GLsizei height,
601 GLenum format, GLenum type, const GLvoid *pixels )
jtgafb833d1999-08-19 00:55:39 +0000602{
Brian Paulfbd8f211999-11-11 01:22:25 +0000603 const struct gl_pixelstore_attrib *unpack = &ctx->Unpack;
604 const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
jtgafb833d1999-08-19 00:55:39 +0000605 const GLint desty = y;
606 GLdepth zspan[MAX_WIDTH];
607 GLboolean quickDraw;
jtgafb833d1999-08-19 00:55:39 +0000608
609 /* Try an optimized glDrawPixels first */
Brian Paulfbd8f211999-11-11 01:22:25 +0000610 if (simple_DrawPixels(ctx, x, y, width, height, format, type, pixels))
jtgafb833d1999-08-19 00:55:39 +0000611 return;
612
jtgafb833d1999-08-19 00:55:39 +0000613 /* Fragment depth values */
Brian Paul7110c371999-11-26 16:27:05 +0000614 if (ctx->Depth.Test || ctx->Fog.Enabled) {
jtgafb833d1999-08-19 00:55:39 +0000615 /* fill in array of z values */
Brian Pauled30dfa2000-03-03 17:47:39 +0000616 GLdepth z = (GLdepth) (ctx->Current.RasterPos[2] * ctx->Visual->DepthMaxF);
Brian Paulfbd8f211999-11-11 01:22:25 +0000617 GLint i;
jtgafb833d1999-08-19 00:55:39 +0000618 for (i=0;i<width;i++) {
619 zspan[i] = z;
620 }
621 }
622
Brian Paulfbd8f211999-11-11 01:22:25 +0000623
624 if (ctx->RasterMask == 0 && !zoom
625 && x >= 0 && y >= 0
Brian Paul3f02f901999-11-24 18:48:30 +0000626 && x + width <= ctx->DrawBuffer->Width
627 && y + height <= ctx->DrawBuffer->Height) {
jtgafb833d1999-08-19 00:55:39 +0000628 quickDraw = GL_TRUE;
629 }
630 else {
631 quickDraw = GL_FALSE;
632 }
633
Brian Paulfbd8f211999-11-11 01:22:25 +0000634 /*
635 * General solution
636 */
jtgafb833d1999-08-19 00:55:39 +0000637 {
jtgafb833d1999-08-19 00:55:39 +0000638 GLubyte rgba[MAX_WIDTH][4];
Brian Paulfbd8f211999-11-11 01:22:25 +0000639 GLint row;
640 if (width > MAX_WIDTH)
641 width = MAX_WIDTH;
642 for (row = 0; row < height; row++, y++) {
643 const GLvoid *source = gl_pixel_addr_in_image(unpack,
644 pixels, width, height, format, type, 0, row, 0);
645 _mesa_unpack_ubyte_color_span(ctx, width, GL_RGBA, (void*) rgba,
646 format, type, source, unpack, GL_TRUE);
jtgafb833d1999-08-19 00:55:39 +0000647
jtgafb833d1999-08-19 00:55:39 +0000648 if (quickDraw) {
Brian Paulfbd8f211999-11-11 01:22:25 +0000649 (*ctx->Driver.WriteRGBASpan)( ctx, width, x, y,
650 (CONST GLubyte (*)[]) rgba, NULL);
jtgafb833d1999-08-19 00:55:39 +0000651 }
652 else if (zoom) {
653 gl_write_zoomed_rgba_span( ctx, width, x, y, zspan,
Brian Paulfbd8f211999-11-11 01:22:25 +0000654 (CONST GLubyte (*)[]) rgba, desty );
jtgafb833d1999-08-19 00:55:39 +0000655 }
656 else {
657 gl_write_rgba_span( ctx, (GLuint) width, x, y, zspan, rgba, GL_BITMAP);
658 }
659 }
jtgafb833d1999-08-19 00:55:39 +0000660 }
661}
662
663
664
665/*
666 * Execute glDrawPixels
667 */
Brian Paulfbd8f211999-11-11 01:22:25 +0000668void
669_mesa_DrawPixels( GLsizei width, GLsizei height,
670 GLenum format, GLenum type, const GLvoid *pixels )
jtgafb833d1999-08-19 00:55:39 +0000671{
Brian Paulfbd8f211999-11-11 01:22:25 +0000672 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +0000673 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glDrawPixels");
674
jtgafb833d1999-08-19 00:55:39 +0000675 if (ctx->RenderMode==GL_RENDER) {
676 GLint x, y;
Brian Paulfbd8f211999-11-11 01:22:25 +0000677 if (!pixels || !ctx->Current.RasterPosValid) {
jtgafb833d1999-08-19 00:55:39 +0000678 return;
679 }
680
681 x = (GLint) (ctx->Current.RasterPos[0] + 0.5F);
682 y = (GLint) (ctx->Current.RasterPos[1] + 0.5F);
683
Brian Paul4ee75bd2000-03-03 15:39:13 +0000684 /* see if device driver can do the drawpix */
685 if (ctx->Driver.DrawPixels
686 && (*ctx->Driver.DrawPixels)(ctx, x, y, width, height, format, type,
687 &ctx->Unpack, pixels)) {
688 return;
689 }
690
Brian Paulfbd8f211999-11-11 01:22:25 +0000691 switch (format) {
jtgafb833d1999-08-19 00:55:39 +0000692 case GL_STENCIL_INDEX:
Brian Paulfbd8f211999-11-11 01:22:25 +0000693 draw_stencil_pixels( ctx, x, y, width, height, type, pixels );
jtgafb833d1999-08-19 00:55:39 +0000694 break;
695 case GL_DEPTH_COMPONENT:
Brian Paulfbd8f211999-11-11 01:22:25 +0000696 draw_depth_pixels( ctx, x, y, width, height, type, pixels );
697 break;
698 case GL_COLOR_INDEX:
699 if (ctx->Visual->RGBAflag)
Brian Paulfbd8f211999-11-11 01:22:25 +0000700 draw_rgba_pixels(ctx, x,y, width, height, format, type, pixels);
Brian Paulbab8f792000-02-08 23:42:14 +0000701 else
702 draw_index_pixels(ctx, x, y, width, height, type, pixels);
jtgafb833d1999-08-19 00:55:39 +0000703 break;
704 case GL_RED:
705 case GL_GREEN:
706 case GL_BLUE:
707 case GL_ALPHA:
jtgafb833d1999-08-19 00:55:39 +0000708 case GL_LUMINANCE:
709 case GL_LUMINANCE_ALPHA:
Brian Paulfbd8f211999-11-11 01:22:25 +0000710 case GL_RGB:
711 case GL_BGR:
jtgafb833d1999-08-19 00:55:39 +0000712 case GL_RGBA:
Brian Paulfbd8f211999-11-11 01:22:25 +0000713 case GL_BGRA:
714 case GL_ABGR_EXT:
715 draw_rgba_pixels(ctx, x, y, width, height, format, type, pixels);
jtgafb833d1999-08-19 00:55:39 +0000716 break;
717 default:
Brian Paulfbd8f211999-11-11 01:22:25 +0000718 gl_error( ctx, GL_INVALID_ENUM, "glDrawPixels(format)" );
jtgafb833d1999-08-19 00:55:39 +0000719 return;
720 }
721 }
722 else if (ctx->RenderMode==GL_FEEDBACK) {
723 if (ctx->Current.RasterPosValid) {
724 GLfloat color[4];
725 GLfloat texcoord[4], invq;
726 UBYTE_RGBA_TO_FLOAT_RGBA(color, ctx->Current.ByteColor);
727 invq = 1.0F / ctx->Current.Texcoord[0][3];
728 texcoord[0] = ctx->Current.Texcoord[0][0] * invq;
729 texcoord[1] = ctx->Current.Texcoord[0][1] * invq;
730 texcoord[2] = ctx->Current.Texcoord[0][2] * invq;
731 texcoord[3] = ctx->Current.Texcoord[0][3];
732 FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_DRAW_PIXEL_TOKEN );
733 gl_feedback_vertex( ctx,
Keith Whitwell1bf9dfa1999-09-18 20:41:22 +0000734 ctx->Current.RasterPos,
jtgafb833d1999-08-19 00:55:39 +0000735 color, ctx->Current.Index, texcoord );
736 }
737 }
738 else if (ctx->RenderMode==GL_SELECT) {
739 if (ctx->Current.RasterPosValid) {
740 gl_update_hitflag( ctx, ctx->Current.RasterPos[2] );
741 }
742 }
743}
744