Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygens_drawpix.c
Go to the documentation of this file.
00001 /* 00002 * Mesa 3-D graphics library 00003 * Version: 7.1 00004 * 00005 * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. 00006 * 00007 * Permission is hereby granted, free of charge, to any person obtaining a 00008 * copy of this software and associated documentation files (the "Software"), 00009 * to deal in the Software without restriction, including without limitation 00010 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 00011 * and/or sell copies of the Software, and to permit persons to whom the 00012 * Software is furnished to do so, subject to the following conditions: 00013 * 00014 * The above copyright notice and this permission notice shall be included 00015 * in all copies or substantial portions of the Software. 00016 * 00017 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 00018 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00019 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 00020 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 00021 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 00022 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 00023 */ 00024 00025 00026 #include "main/glheader.h" 00027 #include "main/bufferobj.h" 00028 #include "main/context.h" 00029 #include "main/convolve.h" 00030 #include "main/image.h" 00031 #include "main/macros.h" 00032 #include "main/imports.h" 00033 #include "main/pixel.h" 00034 #include "main/state.h" 00035 00036 #include "s_context.h" 00037 #include "s_span.h" 00038 #include "s_stencil.h" 00039 #include "s_zoom.h" 00040 00041 00042 00047 static GLboolean 00048 fast_draw_rgba_pixels(GLcontext *ctx, GLint x, GLint y, 00049 GLsizei width, GLsizei height, 00050 GLenum format, GLenum type, 00051 const struct gl_pixelstore_attrib *userUnpack, 00052 const GLvoid *pixels) 00053 { 00054 const GLint imgX = x, imgY = y; 00055 struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0]; 00056 GLenum rbType; 00057 SWcontext *swrast = SWRAST_CONTEXT(ctx); 00058 SWspan span; 00059 GLboolean simpleZoom; 00060 GLint yStep; /* +1 or -1 */ 00061 struct gl_pixelstore_attrib unpack; 00062 GLint destX, destY, drawWidth, drawHeight; /* post clipping */ 00063 00064 if (!rb) 00065 return GL_TRUE; /* no-op */ 00066 00067 rbType = rb->DataType; 00068 00069 if ((swrast->_RasterMask & ~CLIP_BIT) || 00070 ctx->Texture._EnabledCoordUnits || 00071 userUnpack->SwapBytes || 00072 ctx->_ImageTransferState) { 00073 /* can't handle any of those conditions */ 00074 return GL_FALSE; 00075 } 00076 00077 INIT_SPAN(span, GL_BITMAP); 00078 span.arrayMask = SPAN_RGBA; 00079 span.arrayAttribs = FRAG_BIT_COL0; 00080 _swrast_span_default_attribs(ctx, &span); 00081 00082 /* copy input params since clipping may change them */ 00083 unpack = *userUnpack; 00084 destX = x; 00085 destY = y; 00086 drawWidth = width; 00087 drawHeight = height; 00088 00089 /* check for simple zooming and clipping */ 00090 if (ctx->Pixel.ZoomX == 1.0F && 00091 (ctx->Pixel.ZoomY == 1.0F || ctx->Pixel.ZoomY == -1.0F)) { 00092 if (!_mesa_clip_drawpixels(ctx, &destX, &destY, 00093 &drawWidth, &drawHeight, &unpack)) { 00094 /* image was completely clipped: no-op, all done */ 00095 return GL_TRUE; 00096 } 00097 simpleZoom = GL_TRUE; 00098 yStep = (GLint) ctx->Pixel.ZoomY; 00099 ASSERT(yStep == 1 || yStep == -1); 00100 } 00101 else { 00102 /* non-simple zooming */ 00103 simpleZoom = GL_FALSE; 00104 yStep = 1; 00105 if (unpack.RowLength == 0) 00106 unpack.RowLength = width; 00107 } 00108 00109 /* 00110 * Ready to draw! 00111 */ 00112 00113 if (format == GL_RGBA && type == rbType) { 00114 const GLubyte *src 00115 = (const GLubyte *) _mesa_image_address2d(&unpack, pixels, width, 00116 height, format, type, 0, 0); 00117 const GLint srcStride = _mesa_image_row_stride(&unpack, width, 00118 format, type); 00119 if (simpleZoom) { 00120 GLint row; 00121 for (row = 0; row < drawHeight; row++) { 00122 rb->PutRow(ctx, rb, drawWidth, destX, destY, src, NULL); 00123 src += srcStride; 00124 destY += yStep; 00125 } 00126 } 00127 else { 00128 /* with zooming */ 00129 GLint row; 00130 for (row = 0; row < drawHeight; row++) { 00131 span.x = destX; 00132 span.y = destY + row; 00133 span.end = drawWidth; 00134 span.array->ChanType = rbType; 00135 _swrast_write_zoomed_rgba_span(ctx, imgX, imgY, &span, src); 00136 src += srcStride; 00137 } 00138 span.array->ChanType = CHAN_TYPE; 00139 } 00140 return GL_TRUE; 00141 } 00142 00143 if (format == GL_RGB && type == rbType) { 00144 const GLubyte *src 00145 = (const GLubyte *) _mesa_image_address2d(&unpack, pixels, width, 00146 height, format, type, 0, 0); 00147 const GLint srcStride = _mesa_image_row_stride(&unpack, width, 00148 format, type); 00149 if (simpleZoom) { 00150 GLint row; 00151 for (row = 0; row < drawHeight; row++) { 00152 rb->PutRowRGB(ctx, rb, drawWidth, destX, destY, src, NULL); 00153 src += srcStride; 00154 destY += yStep; 00155 } 00156 } 00157 else { 00158 /* with zooming */ 00159 GLint row; 00160 for (row = 0; row < drawHeight; row++) { 00161 span.x = destX; 00162 span.y = destY; 00163 span.end = drawWidth; 00164 span.array->ChanType = rbType; 00165 _swrast_write_zoomed_rgb_span(ctx, imgX, imgY, &span, src); 00166 src += srcStride; 00167 destY++; 00168 } 00169 span.array->ChanType = CHAN_TYPE; 00170 } 00171 return GL_TRUE; 00172 } 00173 00174 /* Remaining cases haven't been tested with alignment != 1 */ 00175 if (userUnpack->Alignment != 1) 00176 return GL_FALSE; 00177 00178 if (format == GL_LUMINANCE && type == CHAN_TYPE && rbType == CHAN_TYPE) { 00179 const GLchan *src = (const GLchan *) pixels 00180 + (unpack.SkipRows * unpack.RowLength + unpack.SkipPixels); 00181 if (simpleZoom) { 00182 /* no zooming */ 00183 GLint row; 00184 ASSERT(drawWidth <= MAX_WIDTH); 00185 for (row = 0; row < drawHeight; row++) { 00186 GLchan rgb[MAX_WIDTH][3]; 00187 GLint i; 00188 for (i = 0;i<drawWidth;i++) { 00189 rgb[i][0] = src[i]; 00190 rgb[i][1] = src[i]; 00191 rgb[i][2] = src[i]; 00192 } 00193 rb->PutRowRGB(ctx, rb, drawWidth, destX, destY, rgb, NULL); 00194 src += unpack.RowLength; 00195 destY += yStep; 00196 } 00197 } 00198 else { 00199 /* with zooming */ 00200 GLint row; 00201 ASSERT(drawWidth <= MAX_WIDTH); 00202 for (row = 0; row < drawHeight; row++) { 00203 GLchan rgb[MAX_WIDTH][3]; 00204 GLint i; 00205 for (i = 0;i<drawWidth;i++) { 00206 rgb[i][0] = src[i]; 00207 rgb[i][1] = src[i]; 00208 rgb[i][2] = src[i]; 00209 } 00210 span.x = destX; 00211 span.y = destY; 00212 span.end = drawWidth; 00213 _swrast_write_zoomed_rgb_span(ctx, imgX, imgY, &span, rgb); 00214 src += unpack.RowLength; 00215 destY++; 00216 } 00217 } 00218 return GL_TRUE; 00219 } 00220 00221 if (format == GL_LUMINANCE_ALPHA && type == CHAN_TYPE && rbType == CHAN_TYPE) { 00222 const GLchan *src = (const GLchan *) pixels 00223 + (unpack.SkipRows * unpack.RowLength + unpack.SkipPixels)*2; 00224 if (simpleZoom) { 00225 GLint row; 00226 ASSERT(drawWidth <= MAX_WIDTH); 00227 for (row = 0; row < drawHeight; row++) { 00228 GLint i; 00229 const GLchan *ptr = src; 00230 for (i = 0;i<drawWidth;i++) { 00231 span.array->rgba[i][0] = *ptr; 00232 span.array->rgba[i][1] = *ptr; 00233 span.array->rgba[i][2] = *ptr++; 00234 span.array->rgba[i][3] = *ptr++; 00235 } 00236 rb->PutRow(ctx, rb, drawWidth, destX, destY, 00237 span.array->rgba, NULL); 00238 src += unpack.RowLength*2; 00239 destY += yStep; 00240 } 00241 } 00242 else { 00243 /* with zooming */ 00244 GLint row; 00245 ASSERT(drawWidth <= MAX_WIDTH); 00246 for (row = 0; row < drawHeight; row++) { 00247 const GLchan *ptr = src; 00248 GLint i; 00249 for (i = 0;i<drawWidth;i++) { 00250 span.array->rgba[i][0] = *ptr; 00251 span.array->rgba[i][1] = *ptr; 00252 span.array->rgba[i][2] = *ptr++; 00253 span.array->rgba[i][3] = *ptr++; 00254 } 00255 span.x = destX; 00256 span.y = destY; 00257 span.end = drawWidth; 00258 _swrast_write_zoomed_rgba_span(ctx, imgX, imgY, &span, 00259 span.array->rgba); 00260 src += unpack.RowLength*2; 00261 destY++; 00262 } 00263 } 00264 return GL_TRUE; 00265 } 00266 00267 if (format == GL_COLOR_INDEX && type == GL_UNSIGNED_BYTE) { 00268 const GLubyte *src = (const GLubyte *) pixels 00269 + unpack.SkipRows * unpack.RowLength + unpack.SkipPixels; 00270 if (ctx->Visual.rgbMode && rbType == GL_UNSIGNED_BYTE) { 00271 /* convert ubyte/CI data to ubyte/RGBA */ 00272 if (simpleZoom) { 00273 GLint row; 00274 for (row = 0; row < drawHeight; row++) { 00275 ASSERT(drawWidth <= MAX_WIDTH); 00276 _mesa_map_ci8_to_rgba8(ctx, drawWidth, src, 00277 span.array->rgba8); 00278 rb->PutRow(ctx, rb, drawWidth, destX, destY, 00279 span.array->rgba8, NULL); 00280 src += unpack.RowLength; 00281 destY += yStep; 00282 } 00283 } 00284 else { 00285 /* ubyte/CI to ubyte/RGBA with zooming */ 00286 GLint row; 00287 for (row = 0; row < drawHeight; row++) { 00288 ASSERT(drawWidth <= MAX_WIDTH); 00289 _mesa_map_ci8_to_rgba8(ctx, drawWidth, src, 00290 span.array->rgba8); 00291 span.x = destX; 00292 span.y = destY; 00293 span.end = drawWidth; 00294 _swrast_write_zoomed_rgba_span(ctx, imgX, imgY, &span, 00295 span.array->rgba8); 00296 src += unpack.RowLength; 00297 destY++; 00298 } 00299 } 00300 return GL_TRUE; 00301 } 00302 else if (!ctx->Visual.rgbMode && rbType == GL_UNSIGNED_INT) { 00303 /* write CI data to CI frame buffer */ 00304 GLint row; 00305 if (simpleZoom) { 00306 for (row = 0; row < drawHeight; row++) { 00307 GLuint index32[MAX_WIDTH]; 00308 GLint col; 00309 for (col = 0; col < drawWidth; col++) 00310 index32[col] = src[col]; 00311 rb->PutRow(ctx, rb, drawWidth, destX, destY, index32, NULL); 00312 src += unpack.RowLength; 00313 destY += yStep; 00314 } 00315 return GL_TRUE; 00316 } 00317 } 00318 } 00319 00320 /* can't handle this pixel format and/or data type */ 00321 return GL_FALSE; 00322 } 00323 00324 00325 00326 /* 00327 * Draw color index image. 00328 */ 00329 static void 00330 draw_index_pixels( GLcontext *ctx, GLint x, GLint y, 00331 GLsizei width, GLsizei height, 00332 GLenum type, 00333 const struct gl_pixelstore_attrib *unpack, 00334 const GLvoid *pixels ) 00335 { 00336 const GLint imgX = x, imgY = y; 00337 const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0; 00338 GLint row, skipPixels; 00339 SWspan span; 00340 00341 INIT_SPAN(span, GL_BITMAP); 00342 span.arrayMask = SPAN_INDEX; 00343 _swrast_span_default_attribs(ctx, &span); 00344 00345 /* 00346 * General solution 00347 */ 00348 skipPixels = 0; 00349 while (skipPixels < width) { 00350 const GLint spanWidth = MIN2(width - skipPixels, MAX_WIDTH); 00351 ASSERT(spanWidth <= MAX_WIDTH); 00352 for (row = 0; row < height; row++) { 00353 const GLvoid *source = _mesa_image_address2d(unpack, pixels, 00354 width, height, 00355 GL_COLOR_INDEX, type, 00356 row, skipPixels); 00357 _mesa_unpack_index_span(ctx, spanWidth, GL_UNSIGNED_INT, 00358 span.array->index, type, source, unpack, 00359 ctx->_ImageTransferState); 00360 00361 /* These may get changed during writing/clipping */ 00362 span.x = x + skipPixels; 00363 span.y = y + row; 00364 span.end = spanWidth; 00365 00366 if (zoom) 00367 _swrast_write_zoomed_index_span(ctx, imgX, imgY, &span); 00368 else 00369 _swrast_write_index_span(ctx, &span); 00370 } 00371 skipPixels += spanWidth; 00372 } 00373 } 00374 00375 00376 00377 /* 00378 * Draw stencil image. 00379 */ 00380 static void 00381 draw_stencil_pixels( GLcontext *ctx, GLint x, GLint y, 00382 GLsizei width, GLsizei height, 00383 GLenum type, 00384 const struct gl_pixelstore_attrib *unpack, 00385 const GLvoid *pixels ) 00386 { 00387 const GLboolean zoom = ctx->Pixel.ZoomX != 1.0 || ctx->Pixel.ZoomY != 1.0; 00388 GLint skipPixels; 00389 00390 /* if width > MAX_WIDTH, have to process image in chunks */ 00391 skipPixels = 0; 00392 while (skipPixels < width) { 00393 const GLint spanX = x + skipPixels; 00394 const GLint spanWidth = MIN2(width - skipPixels, MAX_WIDTH); 00395 GLint row; 00396 for (row = 0; row < height; row++) { 00397 const GLint spanY = y + row; 00398 GLstencil values[MAX_WIDTH]; 00399 GLenum destType = (sizeof(GLstencil) == sizeof(GLubyte)) 00400 ? GL_UNSIGNED_BYTE : GL_UNSIGNED_SHORT; 00401 const GLvoid *source = _mesa_image_address2d(unpack, pixels, 00402 width, height, 00403 GL_COLOR_INDEX, type, 00404 row, skipPixels); 00405 _mesa_unpack_stencil_span(ctx, spanWidth, destType, values, 00406 type, source, unpack, 00407 ctx->_ImageTransferState); 00408 if (zoom) { 00409 _swrast_write_zoomed_stencil_span(ctx, x, y, spanWidth, 00410 spanX, spanY, values); 00411 } 00412 else { 00413 _swrast_write_stencil_span(ctx, spanWidth, spanX, spanY, values); 00414 } 00415 } 00416 skipPixels += spanWidth; 00417 } 00418 } 00419 00420 00421 /* 00422 * Draw depth image. 00423 */ 00424 static void 00425 draw_depth_pixels( GLcontext *ctx, GLint x, GLint y, 00426 GLsizei width, GLsizei height, 00427 GLenum type, 00428 const struct gl_pixelstore_attrib *unpack, 00429 const GLvoid *pixels ) 00430 { 00431 const GLboolean scaleOrBias 00432 = ctx->Pixel.DepthScale != 1.0 || ctx->Pixel.DepthBias != 0.0; 00433 const GLboolean zoom = ctx->Pixel.ZoomX != 1.0 || ctx->Pixel.ZoomY != 1.0; 00434 SWspan span; 00435 00436 INIT_SPAN(span, GL_BITMAP); 00437 span.arrayMask = SPAN_Z; 00438 _swrast_span_default_attribs(ctx, &span); 00439 00440 if (type == GL_UNSIGNED_SHORT 00441 && ctx->DrawBuffer->Visual.depthBits == 16 00442 && !scaleOrBias 00443 && !zoom 00444 && ctx->Visual.rgbMode 00445 && width <= MAX_WIDTH 00446 && !unpack->SwapBytes) { 00447 /* Special case: directly write 16-bit depth values */ 00448 GLint row; 00449 for (row = 0; row < height; row++) { 00450 const GLushort *zSrc = (const GLushort *) 00451 _mesa_image_address2d(unpack, pixels, width, height, 00452 GL_DEPTH_COMPONENT, type, row, 0); 00453 GLint i; 00454 for (i = 0; i < width; i++) 00455 span.array->z[i] = zSrc[i]; 00456 span.x = x; 00457 span.y = y + row; 00458 span.end = width; 00459 _swrast_write_rgba_span(ctx, &span); 00460 } 00461 } 00462 else if (type == GL_UNSIGNED_INT 00463 && !scaleOrBias 00464 && !zoom 00465 && ctx->Visual.rgbMode 00466 && width <= MAX_WIDTH 00467 && !unpack->SwapBytes) { 00468 /* Special case: shift 32-bit values down to Visual.depthBits */ 00469 const GLint shift = 32 - ctx->DrawBuffer->Visual.depthBits; 00470 GLint row; 00471 for (row = 0; row < height; row++) { 00472 const GLuint *zSrc = (const GLuint *) 00473 _mesa_image_address2d(unpack, pixels, width, height, 00474 GL_DEPTH_COMPONENT, type, row, 0); 00475 if (shift == 0) { 00476 _mesa_memcpy(span.array->z, zSrc, width * sizeof(GLuint)); 00477 } 00478 else { 00479 GLint col; 00480 for (col = 0; col < width; col++) 00481 span.array->z[col] = zSrc[col] >> shift; 00482 } 00483 span.x = x; 00484 span.y = y + row; 00485 span.end = width; 00486 _swrast_write_rgba_span(ctx, &span); 00487 } 00488 } 00489 else { 00490 /* General case */ 00491 const GLuint depthMax = ctx->DrawBuffer->_DepthMax; 00492 GLint skipPixels = 0; 00493 00494 /* in case width > MAX_WIDTH do the copy in chunks */ 00495 while (skipPixels < width) { 00496 const GLint spanWidth = MIN2(width - skipPixels, MAX_WIDTH); 00497 GLint row; 00498 ASSERT(span.end <= MAX_WIDTH); 00499 for (row = 0; row < height; row++) { 00500 const GLvoid *zSrc = _mesa_image_address2d(unpack, 00501 pixels, width, height, 00502 GL_DEPTH_COMPONENT, type, 00503 row, skipPixels); 00504 00505 /* Set these for each row since the _swrast_write_* function may 00506 * change them while clipping. 00507 */ 00508 span.x = x + skipPixels; 00509 span.y = y + row; 00510 span.end = spanWidth; 00511 00512 _mesa_unpack_depth_span(ctx, spanWidth, 00513 GL_UNSIGNED_INT, span.array->z, depthMax, 00514 type, zSrc, unpack); 00515 if (zoom) { 00516 _swrast_write_zoomed_depth_span(ctx, x, y, &span); 00517 } 00518 else if (ctx->Visual.rgbMode) { 00519 _swrast_write_rgba_span(ctx, &span); 00520 } 00521 else { 00522 _swrast_write_index_span(ctx, &span); 00523 } 00524 } 00525 skipPixels += spanWidth; 00526 } 00527 } 00528 } 00529 00530 00531 00535 static void 00536 draw_rgba_pixels( GLcontext *ctx, GLint x, GLint y, 00537 GLsizei width, GLsizei height, 00538 GLenum format, GLenum type, 00539 const struct gl_pixelstore_attrib *unpack, 00540 const GLvoid *pixels ) 00541 { 00542 const GLint imgX = x, imgY = y; 00543 const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0; 00544 GLfloat *convImage = NULL; 00545 GLbitfield transferOps = ctx->_ImageTransferState; 00546 SWspan span; 00547 00548 /* Try an optimized glDrawPixels first */ 00549 if (fast_draw_rgba_pixels(ctx, x, y, width, height, format, type, 00550 unpack, pixels)) { 00551 return; 00552 } 00553 00554 INIT_SPAN(span, GL_BITMAP); 00555 _swrast_span_default_attribs(ctx, &span); 00556 span.arrayMask = SPAN_RGBA; 00557 span.arrayAttribs = FRAG_BIT_COL0; /* we're fill in COL0 attrib values */ 00558 00559 if (ctx->Pixel.Convolution2DEnabled || ctx->Pixel.Separable2DEnabled) { 00560 /* Convolution has to be handled specially. We'll create an 00561 * intermediate image, applying all pixel transfer operations 00562 * up to convolution. Then we'll convolve the image. Then 00563 * we'll proceed with the rest of the transfer operations and 00564 * rasterize the image. 00565 */ 00566 GLint row; 00567 GLfloat *dest, *tmpImage; 00568 00569 tmpImage = (GLfloat *) _mesa_malloc(width * height * 4 * sizeof(GLfloat)); 00570 if (!tmpImage) { 00571 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels"); 00572 return; 00573 } 00574 convImage = (GLfloat *) _mesa_malloc(width * height * 4 * sizeof(GLfloat)); 00575 if (!convImage) { 00576 _mesa_free(tmpImage); 00577 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels"); 00578 return; 00579 } 00580 00581 /* Unpack the image and apply transfer ops up to convolution */ 00582 dest = tmpImage; 00583 for (row = 0; row < height; row++) { 00584 const GLvoid *source = _mesa_image_address2d(unpack, 00585 pixels, width, height, format, type, row, 0); 00586 _mesa_unpack_color_span_float(ctx, width, GL_RGBA, (GLfloat *) dest, 00587 format, type, source, unpack, 00588 transferOps & IMAGE_PRE_CONVOLUTION_BITS); 00589 dest += width * 4; 00590 } 00591 00592 /* do convolution */ 00593 if (ctx->Pixel.Convolution2DEnabled) { 00594 _mesa_convolve_2d_image(ctx, &width, &height, tmpImage, convImage); 00595 } 00596 else { 00597 ASSERT(ctx->Pixel.Separable2DEnabled); 00598 _mesa_convolve_sep_image(ctx, &width, &height, tmpImage, convImage); 00599 } 00600 _mesa_free(tmpImage); 00601 00602 /* continue transfer ops and draw the convolved image */ 00603 unpack = &ctx->DefaultPacking; 00604 pixels = convImage; 00605 format = GL_RGBA; 00606 type = GL_FLOAT; 00607 transferOps &= IMAGE_POST_CONVOLUTION_BITS; 00608 } 00609 else if (ctx->Pixel.Convolution1DEnabled) { 00610 /* we only want to apply 1D convolution to glTexImage1D */ 00611 transferOps &= ~(IMAGE_CONVOLUTION_BIT | 00612 IMAGE_POST_CONVOLUTION_SCALE_BIAS); 00613 } 00614 00615 if (ctx->DrawBuffer->_NumColorDrawBuffers > 0 && 00616 ctx->DrawBuffer->_ColorDrawBuffers[0]->DataType != GL_FLOAT && 00617 ctx->Color.ClampFragmentColor != GL_FALSE) { 00618 /* need to clamp colors before applying fragment ops */ 00619 transferOps |= IMAGE_CLAMP_BIT; 00620 } 00621 00622 /* 00623 * General solution 00624 */ 00625 { 00626 const GLboolean sink = (ctx->Pixel.MinMaxEnabled && ctx->MinMax.Sink) 00627 || (ctx->Pixel.HistogramEnabled && ctx->Histogram.Sink); 00628 const GLbitfield interpMask = span.interpMask; 00629 const GLbitfield arrayMask = span.arrayMask; 00630 const GLint srcStride 00631 = _mesa_image_row_stride(unpack, width, format, type); 00632 GLint skipPixels = 0; 00633 /* use span array for temp color storage */ 00634 GLfloat *rgba = (GLfloat *) span.array->attribs[FRAG_ATTRIB_COL0]; 00635 00636 /* if the span is wider than MAX_WIDTH we have to do it in chunks */ 00637 while (skipPixels < width) { 00638 const GLint spanWidth = MIN2(width - skipPixels, MAX_WIDTH); 00639 const GLubyte *source 00640 = (const GLubyte *) _mesa_image_address2d(unpack, pixels, 00641 width, height, format, 00642 type, 0, skipPixels); 00643 GLint row; 00644 00645 for (row = 0; row < height; row++) { 00646 /* get image row as float/RGBA */ 00647 _mesa_unpack_color_span_float(ctx, spanWidth, GL_RGBA, rgba, 00648 format, type, source, unpack, 00649 transferOps); 00650 /* draw the span */ 00651 if (!sink) { 00652 /* Set these for each row since the _swrast_write_* functions 00653 * may change them while clipping/rendering. 00654 */ 00655 span.array->ChanType = GL_FLOAT; 00656 span.x = x + skipPixels; 00657 span.y = y + row; 00658 span.end = spanWidth; 00659 span.arrayMask = arrayMask; 00660 span.interpMask = interpMask; 00661 if (zoom) { 00662 _swrast_write_zoomed_rgba_span(ctx, imgX, imgY, &span, rgba); 00663 } 00664 else { 00665 _swrast_write_rgba_span(ctx, &span); 00666 } 00667 } 00668 00669 source += srcStride; 00670 } /* for row */ 00671 00672 skipPixels += spanWidth; 00673 } /* while skipPixels < width */ 00674 00675 /* XXX this is ugly/temporary, to undo above change */ 00676 span.array->ChanType = CHAN_TYPE; 00677 } 00678 00679 if (convImage) { 00680 _mesa_free(convImage); 00681 } 00682 } 00683 00684 00693 static void 00694 draw_depth_stencil_pixels(GLcontext *ctx, GLint x, GLint y, 00695 GLsizei width, GLsizei height, GLenum type, 00696 const struct gl_pixelstore_attrib *unpack, 00697 const GLvoid *pixels) 00698 { 00699 const GLint imgX = x, imgY = y; 00700 const GLboolean scaleOrBias 00701 = ctx->Pixel.DepthScale != 1.0 || ctx->Pixel.DepthBias != 0.0; 00702 const GLuint depthMax = ctx->DrawBuffer->_DepthMax; 00703 const GLuint stencilMask = ctx->Stencil.WriteMask[0]; 00704 const GLuint stencilType = (STENCIL_BITS == 8) ? 00705 GL_UNSIGNED_BYTE : GL_UNSIGNED_SHORT; 00706 const GLboolean zoom = ctx->Pixel.ZoomX != 1.0 || ctx->Pixel.ZoomY != 1.0; 00707 struct gl_renderbuffer *depthRb, *stencilRb; 00708 struct gl_pixelstore_attrib clippedUnpack = *unpack; 00709 00710 if (!zoom) { 00711 if (!_mesa_clip_drawpixels(ctx, &x, &y, &width, &height, 00712 &clippedUnpack)) { 00713 /* totally clipped */ 00714 return; 00715 } 00716 } 00717 00718 depthRb = ctx->ReadBuffer->Attachment[BUFFER_DEPTH].Renderbuffer; 00719 stencilRb = ctx->ReadBuffer->Attachment[BUFFER_STENCIL].Renderbuffer; 00720 ASSERT(depthRb); 00721 ASSERT(stencilRb); 00722 00723 if (depthRb->_BaseFormat == GL_DEPTH_STENCIL_EXT && 00724 stencilRb->_BaseFormat == GL_DEPTH_STENCIL_EXT && 00725 depthRb == stencilRb && 00726 !scaleOrBias && 00727 !zoom && 00728 ctx->Depth.Mask && 00729 (stencilMask & 0xff) == 0xff) { 00730 /* This is the ideal case. 00731 * Drawing GL_DEPTH_STENCIL pixels into a combined depth/stencil buffer. 00732 * Plus, no pixel transfer ops, zooming, or masking needed. 00733 */ 00734 GLint i; 00735 for (i = 0; i < height; i++) { 00736 const GLuint *src = (const GLuint *) 00737 _mesa_image_address2d(&clippedUnpack, pixels, width, height, 00738 GL_DEPTH_STENCIL_EXT, type, i, 0); 00739 depthRb->PutRow(ctx, depthRb, width, x, y + i, src, NULL); 00740 } 00741 } 00742 else { 00743 /* sub-optimal cases: 00744 * Separate depth/stencil buffers, or pixel transfer ops required. 00745 */ 00746 /* XXX need to handle very wide images (skippixels) */ 00747 GLint i; 00748 00749 depthRb = ctx->DrawBuffer->_DepthBuffer; 00750 stencilRb = ctx->DrawBuffer->_StencilBuffer; 00751 00752 for (i = 0; i < height; i++) { 00753 const GLuint *depthStencilSrc = (const GLuint *) 00754 _mesa_image_address2d(&clippedUnpack, pixels, width, height, 00755 GL_DEPTH_STENCIL_EXT, type, i, 0); 00756 00757 if (ctx->Depth.Mask) { 00758 if (!scaleOrBias && ctx->DrawBuffer->Visual.depthBits == 24) { 00759 /* fast path 24-bit zbuffer */ 00760 GLuint zValues[MAX_WIDTH]; 00761 GLint j; 00762 ASSERT(depthRb->DataType == GL_UNSIGNED_INT); 00763 for (j = 0; j < width; j++) { 00764 zValues[j] = depthStencilSrc[j] >> 8; 00765 } 00766 if (zoom) 00767 _swrast_write_zoomed_z_span(ctx, imgX, imgY, width, 00768 x, y + i, zValues); 00769 else 00770 depthRb->PutRow(ctx, depthRb, width, x, y + i, zValues,NULL); 00771 } 00772 else if (!scaleOrBias && ctx->DrawBuffer->Visual.depthBits == 16) { 00773 /* fast path 16-bit zbuffer */ 00774 GLushort zValues[MAX_WIDTH]; 00775 GLint j; 00776 ASSERT(depthRb->DataType == GL_UNSIGNED_SHORT); 00777 for (j = 0; j < width; j++) { 00778 zValues[j] = depthStencilSrc[j] >> 16; 00779 } 00780 if (zoom) 00781 _swrast_write_zoomed_z_span(ctx, imgX, imgY, width, 00782 x, y + i, zValues); 00783 else 00784 depthRb->PutRow(ctx, depthRb, width, x, y + i, zValues,NULL); 00785 } 00786 else { 00787 /* general case */ 00788 GLuint zValues[MAX_WIDTH]; /* 16 or 32-bit Z value storage */ 00789 _mesa_unpack_depth_span(ctx, width, 00790 depthRb->DataType, zValues, depthMax, 00791 type, depthStencilSrc, &clippedUnpack); 00792 if (zoom) { 00793 _swrast_write_zoomed_z_span(ctx, imgX, imgY, width, x, 00794 y + i, zValues); 00795 } 00796 else { 00797 depthRb->PutRow(ctx, depthRb, width, x, y + i, zValues,NULL); 00798 } 00799 } 00800 } 00801 00802 if (stencilMask != 0x0) { 00803 GLstencil stencilValues[MAX_WIDTH]; 00804 /* get stencil values, with shift/offset/mapping */ 00805 _mesa_unpack_stencil_span(ctx, width, stencilType, stencilValues, 00806 type, depthStencilSrc, &clippedUnpack, 00807 ctx->_ImageTransferState); 00808 if (zoom) 00809 _swrast_write_zoomed_stencil_span(ctx, imgX, imgY, width, 00810 x, y + i, stencilValues); 00811 else 00812 _swrast_write_stencil_span(ctx, width, x, y + i, stencilValues); 00813 } 00814 } 00815 } 00816 } 00817 00818 00823 void 00824 _swrast_DrawPixels( GLcontext *ctx, 00825 GLint x, GLint y, 00826 GLsizei width, GLsizei height, 00827 GLenum format, GLenum type, 00828 const struct gl_pixelstore_attrib *unpack, 00829 const GLvoid *pixels ) 00830 { 00831 SWcontext *swrast = SWRAST_CONTEXT(ctx); 00832 00833 RENDER_START(swrast,ctx); 00834 00835 if (ctx->NewState) 00836 _mesa_update_state(ctx); 00837 00838 if (swrast->NewState) 00839 _swrast_validate_derived( ctx ); 00840 00841 pixels = _mesa_map_drawpix_pbo(ctx, unpack, pixels); 00842 if (!pixels) { 00843 RENDER_FINISH(swrast,ctx); 00844 return; 00845 } 00846 00847 switch (format) { 00848 case GL_STENCIL_INDEX: 00849 draw_stencil_pixels( ctx, x, y, width, height, type, unpack, pixels ); 00850 break; 00851 case GL_DEPTH_COMPONENT: 00852 draw_depth_pixels( ctx, x, y, width, height, type, unpack, pixels ); 00853 break; 00854 case GL_COLOR_INDEX: 00855 if (ctx->Visual.rgbMode) 00856 draw_rgba_pixels(ctx, x,y, width, height, format, type, unpack, pixels); 00857 else 00858 draw_index_pixels(ctx, x, y, width, height, type, unpack, pixels); 00859 break; 00860 case GL_RED: 00861 case GL_GREEN: 00862 case GL_BLUE: 00863 case GL_ALPHA: 00864 case GL_LUMINANCE: 00865 case GL_LUMINANCE_ALPHA: 00866 case GL_RGB: 00867 case GL_BGR: 00868 case GL_RGBA: 00869 case GL_BGRA: 00870 case GL_ABGR_EXT: 00871 draw_rgba_pixels(ctx, x, y, width, height, format, type, unpack, pixels); 00872 break; 00873 case GL_DEPTH_STENCIL_EXT: 00874 draw_depth_stencil_pixels(ctx, x, y, width, height, 00875 type, unpack, pixels); 00876 break; 00877 default: 00878 _mesa_problem(ctx, "unexpected format in _swrast_DrawPixels"); 00879 /* don't return yet, clean-up */ 00880 } 00881 00882 RENDER_FINISH(swrast,ctx); 00883 00884 _mesa_unmap_drapix_pbo(ctx, unpack); 00885 } 00886 00887 00888 00889 #if 0 /* experimental */ 00890 /* 00891 * Execute glDrawDepthPixelsMESA(). 00892 */ 00893 void 00894 _swrast_DrawDepthPixelsMESA( GLcontext *ctx, 00895 GLint x, GLint y, 00896 GLsizei width, GLsizei height, 00897 GLenum colorFormat, GLenum colorType, 00898 const GLvoid *colors, 00899 GLenum depthType, const GLvoid *depths, 00900 const struct gl_pixelstore_attrib *unpack ) 00901 { 00902 SWcontext *swrast = SWRAST_CONTEXT(ctx); 00903 00904 if (swrast->NewState) 00905 _swrast_validate_derived( ctx ); 00906 00907 RENDER_START(swrast,ctx); 00908 00909 switch (colorFormat) { 00910 case GL_COLOR_INDEX: 00911 if (ctx->Visual.rgbMode) 00912 draw_rgba_pixels(ctx, x,y, width, height, colorFormat, colorType, 00913 unpack, colors); 00914 else 00915 draw_index_pixels(ctx, x, y, width, height, colorType, 00916 unpack, colors); 00917 break; 00918 case GL_RED: 00919 case GL_GREEN: 00920 case GL_BLUE: 00921 case GL_ALPHA: 00922 case GL_LUMINANCE: 00923 case GL_LUMINANCE_ALPHA: 00924 case GL_RGB: 00925 case GL_BGR: 00926 case GL_RGBA: 00927 case GL_BGRA: 00928 case GL_ABGR_EXT: 00929 draw_rgba_pixels(ctx, x, y, width, height, colorFormat, colorType, 00930 unpack, colors); 00931 break; 00932 default: 00933 _mesa_problem(ctx, "unexpected format in glDrawDepthPixelsMESA"); 00934 } 00935 00936 RENDER_FINISH(swrast,ctx); 00937 } 00938 #endif Generated on Sat May 26 2012 04:19:32 for ReactOS by
1.7.6.1
|