Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenframebuffer.c
Go to the documentation of this file.
00001 /* 00002 * Mesa 3-D graphics library 00003 * Version: 7.2 00004 * 00005 * Copyright (C) 1999-2008 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 00033 #include "glheader.h" 00034 #include "imports.h" 00035 #include "buffers.h" 00036 #include "context.h" 00037 #include "depthstencil.h" 00038 #include "mtypes.h" 00039 #include "fbobject.h" 00040 #include "framebuffer.h" 00041 #include "renderbuffer.h" 00042 #include "texobj.h" 00043 00044 00045 00050 static void 00051 compute_depth_max(struct gl_framebuffer *fb) 00052 { 00053 if (fb->Visual.depthBits == 0) { 00054 /* Special case. Even if we don't have a depth buffer we need 00055 * good values for DepthMax for Z vertex transformation purposes 00056 * and for per-fragment fog computation. 00057 */ 00058 fb->_DepthMax = (1 << 16) - 1; 00059 } 00060 else if (fb->Visual.depthBits < 32) { 00061 fb->_DepthMax = (1 << fb->Visual.depthBits) - 1; 00062 } 00063 else { 00064 /* Special case since shift values greater than or equal to the 00065 * number of bits in the left hand expression's type are undefined. 00066 */ 00067 fb->_DepthMax = 0xffffffff; 00068 } 00069 fb->_DepthMaxF = (GLfloat) fb->_DepthMax; 00070 00071 /* Minimum resolvable depth value, for polygon offset */ 00072 fb->_MRD = (GLfloat)1.0 / fb->_DepthMaxF; 00073 } 00074 00075 00083 struct gl_framebuffer * 00084 _mesa_create_framebuffer(const GLvisual *visual) 00085 { 00086 struct gl_framebuffer *fb = CALLOC_STRUCT(gl_framebuffer); 00087 assert(visual); 00088 if (fb) { 00089 _mesa_initialize_framebuffer(fb, visual); 00090 } 00091 return fb; 00092 } 00093 00094 00102 struct gl_framebuffer * 00103 _mesa_new_framebuffer(GLcontext *ctx, GLuint name) 00104 { 00105 struct gl_framebuffer *fb; 00106 (void) ctx; 00107 assert(name != 0); 00108 fb = CALLOC_STRUCT(gl_framebuffer); 00109 if (fb) { 00110 fb->Name = name; 00111 fb->RefCount = 1; 00112 fb->_NumColorDrawBuffers = 1; 00113 fb->ColorDrawBuffer[0] = GL_COLOR_ATTACHMENT0_EXT; 00114 fb->_ColorDrawBufferIndexes[0] = BUFFER_COLOR0; 00115 fb->ColorReadBuffer = GL_COLOR_ATTACHMENT0_EXT; 00116 fb->_ColorReadBufferIndex = BUFFER_COLOR0; 00117 fb->Delete = _mesa_destroy_framebuffer; 00118 _glthread_INIT_MUTEX(fb->Mutex); 00119 } 00120 return fb; 00121 } 00122 00123 00129 void 00130 _mesa_initialize_framebuffer(struct gl_framebuffer *fb, const GLvisual *visual) 00131 { 00132 assert(fb); 00133 assert(visual); 00134 00135 _mesa_bzero(fb, sizeof(struct gl_framebuffer)); 00136 00137 _glthread_INIT_MUTEX(fb->Mutex); 00138 00139 fb->RefCount = 1; 00140 00141 /* save the visual */ 00142 fb->Visual = *visual; 00143 00144 /* Init read/draw renderbuffer state */ 00145 if (visual->doubleBufferMode) { 00146 fb->_NumColorDrawBuffers = 1; 00147 fb->ColorDrawBuffer[0] = GL_BACK; 00148 fb->_ColorDrawBufferIndexes[0] = BUFFER_BACK_LEFT; 00149 fb->ColorReadBuffer = GL_BACK; 00150 fb->_ColorReadBufferIndex = BUFFER_BACK_LEFT; 00151 } 00152 else { 00153 fb->_NumColorDrawBuffers = 1; 00154 fb->ColorDrawBuffer[0] = GL_FRONT; 00155 fb->_ColorDrawBufferIndexes[0] = BUFFER_FRONT_LEFT; 00156 fb->ColorReadBuffer = GL_FRONT; 00157 fb->_ColorReadBufferIndex = BUFFER_FRONT_LEFT; 00158 } 00159 00160 fb->Delete = _mesa_destroy_framebuffer; 00161 fb->_Status = GL_FRAMEBUFFER_COMPLETE_EXT; 00162 00163 compute_depth_max(fb); 00164 } 00165 00166 00171 void 00172 _mesa_destroy_framebuffer(struct gl_framebuffer *fb) 00173 { 00174 if (fb) { 00175 _mesa_free_framebuffer_data(fb); 00176 _mesa_free(fb); 00177 } 00178 } 00179 00180 00185 void 00186 _mesa_free_framebuffer_data(struct gl_framebuffer *fb) 00187 { 00188 GLuint i; 00189 00190 assert(fb); 00191 assert(fb->RefCount == 0); 00192 00193 _glthread_DESTROY_MUTEX(fb->Mutex); 00194 00195 for (i = 0; i < BUFFER_COUNT; i++) { 00196 struct gl_renderbuffer_attachment *att = &fb->Attachment[i]; 00197 if (att->Renderbuffer) { 00198 _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); 00199 } 00200 if (att->Texture) { 00201 _mesa_reference_texobj(&att->Texture, NULL); 00202 } 00203 ASSERT(!att->Renderbuffer); 00204 ASSERT(!att->Texture); 00205 att->Type = GL_NONE; 00206 } 00207 00208 /* unbind _Depth/_StencilBuffer to decr ref counts */ 00209 _mesa_reference_renderbuffer(&fb->_DepthBuffer, NULL); 00210 _mesa_reference_renderbuffer(&fb->_StencilBuffer, NULL); 00211 } 00212 00213 00217 void 00218 _mesa_reference_framebuffer(struct gl_framebuffer **ptr, 00219 struct gl_framebuffer *fb) 00220 { 00221 assert(ptr); 00222 if (*ptr == fb) { 00223 /* no change */ 00224 return; 00225 } 00226 if (*ptr) { 00227 _mesa_unreference_framebuffer(ptr); 00228 } 00229 assert(!*ptr); 00230 assert(fb); 00231 _glthread_LOCK_MUTEX(fb->Mutex); 00232 fb->RefCount++; 00233 _glthread_UNLOCK_MUTEX(fb->Mutex); 00234 *ptr = fb; 00235 } 00236 00237 00244 void 00245 _mesa_unreference_framebuffer(struct gl_framebuffer **fb) 00246 { 00247 assert(fb); 00248 if (*fb) { 00249 GLboolean deleteFlag = GL_FALSE; 00250 00251 _glthread_LOCK_MUTEX((*fb)->Mutex); 00252 ASSERT((*fb)->RefCount > 0); 00253 (*fb)->RefCount--; 00254 deleteFlag = ((*fb)->RefCount == 0); 00255 _glthread_UNLOCK_MUTEX((*fb)->Mutex); 00256 00257 if (deleteFlag) 00258 (*fb)->Delete(*fb); 00259 00260 *fb = NULL; 00261 } 00262 } 00263 00264 00265 00266 00277 void 00278 _mesa_resize_framebuffer(GLcontext *ctx, struct gl_framebuffer *fb, 00279 GLuint width, GLuint height) 00280 { 00281 GLuint i; 00282 00283 /* XXX I think we could check if the size is not changing 00284 * and return early. 00285 */ 00286 00287 /* For window system framebuffers, Name is zero */ 00288 assert(fb->Name == 0); 00289 00290 for (i = 0; i < BUFFER_COUNT; i++) { 00291 struct gl_renderbuffer_attachment *att = &fb->Attachment[i]; 00292 if (att->Type == GL_RENDERBUFFER_EXT && att->Renderbuffer) { 00293 struct gl_renderbuffer *rb = att->Renderbuffer; 00294 /* only resize if size is changing */ 00295 if (rb->Width != width || rb->Height != height) { 00296 /* could just as well pass rb->_ActualFormat here */ 00297 if (rb->AllocStorage(ctx, rb, rb->InternalFormat, width, height)) { 00298 ASSERT(rb->Width == width); 00299 ASSERT(rb->Height == height); 00300 } 00301 else { 00302 _mesa_error(ctx, GL_OUT_OF_MEMORY, "Resizing framebuffer"); 00303 /* no return */ 00304 } 00305 } 00306 } 00307 } 00308 00309 if (fb->_DepthBuffer) { 00310 struct gl_renderbuffer *rb = fb->_DepthBuffer; 00311 if (rb->Width != width || rb->Height != height) { 00312 if (!rb->AllocStorage(ctx, rb, rb->InternalFormat, width, height)) { 00313 _mesa_error(ctx, GL_OUT_OF_MEMORY, "Resizing framebuffer"); 00314 } 00315 } 00316 } 00317 00318 if (fb->_StencilBuffer) { 00319 struct gl_renderbuffer *rb = fb->_StencilBuffer; 00320 if (rb->Width != width || rb->Height != height) { 00321 if (!rb->AllocStorage(ctx, rb, rb->InternalFormat, width, height)) { 00322 _mesa_error(ctx, GL_OUT_OF_MEMORY, "Resizing framebuffer"); 00323 } 00324 } 00325 } 00326 00327 fb->Width = width; 00328 fb->Height = height; 00329 00330 if (ctx) { 00331 /* update scissor / window bounds */ 00332 _mesa_update_draw_buffer_bounds(ctx); 00333 /* Signal new buffer state so that swrast will update its clipping 00334 * info (the CLIP_BIT flag). 00335 */ 00336 ctx->NewState |= _NEW_BUFFERS; 00337 } 00338 } 00339 00340 00341 00356 void 00357 _mesa_resizebuffers( GLcontext *ctx ) 00358 { 00359 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH( ctx ); 00360 00361 if (MESA_VERBOSE & VERBOSE_API) 00362 _mesa_debug(ctx, "glResizeBuffersMESA\n"); 00363 00364 if (!ctx->Driver.GetBufferSize) { 00365 return; 00366 } 00367 00368 if (ctx->WinSysDrawBuffer) { 00369 GLuint newWidth, newHeight; 00370 GLframebuffer *buffer = ctx->WinSysDrawBuffer; 00371 00372 assert(buffer->Name == 0); 00373 00374 /* ask device driver for size of output buffer */ 00375 ctx->Driver.GetBufferSize( buffer, &newWidth, &newHeight ); 00376 00377 /* see if size of device driver's color buffer (window) has changed */ 00378 if (buffer->Width != newWidth || buffer->Height != newHeight) { 00379 if (ctx->Driver.ResizeBuffers) 00380 ctx->Driver.ResizeBuffers(ctx, buffer, newWidth, newHeight ); 00381 } 00382 } 00383 00384 if (ctx->WinSysReadBuffer 00385 && ctx->WinSysReadBuffer != ctx->WinSysDrawBuffer) { 00386 GLuint newWidth, newHeight; 00387 GLframebuffer *buffer = ctx->WinSysReadBuffer; 00388 00389 assert(buffer->Name == 0); 00390 00391 /* ask device driver for size of read buffer */ 00392 ctx->Driver.GetBufferSize( buffer, &newWidth, &newHeight ); 00393 00394 /* see if size of device driver's color buffer (window) has changed */ 00395 if (buffer->Width != newWidth || buffer->Height != newHeight) { 00396 if (ctx->Driver.ResizeBuffers) 00397 ctx->Driver.ResizeBuffers(ctx, buffer, newWidth, newHeight ); 00398 } 00399 } 00400 00401 ctx->NewState |= _NEW_BUFFERS; /* to update scissor / window bounds */ 00402 } 00403 00404 00405 /* 00406 * XXX THIS IS OBSOLETE 00407 */ 00408 void GLAPIENTRY 00409 _mesa_ResizeBuffersMESA( void ) 00410 { 00411 GET_CURRENT_CONTEXT(ctx); 00412 00413 if (ctx->Extensions.MESA_resize_buffers) 00414 _mesa_resizebuffers( ctx ); 00415 } 00416 00417 00418 00426 static void 00427 update_framebuffer_size(struct gl_framebuffer *fb) 00428 { 00429 GLboolean haveSize = GL_FALSE; 00430 GLuint i; 00431 00432 /* user-created framebuffers only */ 00433 assert(fb->Name); 00434 00435 for (i = 0; i < BUFFER_COUNT; i++) { 00436 struct gl_renderbuffer_attachment *att = &fb->Attachment[i]; 00437 const struct gl_renderbuffer *rb = att->Renderbuffer; 00438 if (rb) { 00439 if (haveSize) { 00440 if (rb->Width != fb->Width && rb->Height != fb->Height) { 00441 /* size mismatch! */ 00442 fb->Width = 0; 00443 fb->Height = 0; 00444 return; 00445 } 00446 } 00447 else { 00448 fb->Width = rb->Width; 00449 fb->Height = rb->Height; 00450 haveSize = GL_TRUE; 00451 } 00452 } 00453 } 00454 } 00455 00456 00463 void 00464 _mesa_update_draw_buffer_bounds(GLcontext *ctx) 00465 { 00466 struct gl_framebuffer *buffer = ctx->DrawBuffer; 00467 00468 if (!buffer) 00469 return; 00470 00471 if (buffer->Name) { 00472 /* user-created framebuffer size depends on the renderbuffers */ 00473 update_framebuffer_size(buffer); 00474 } 00475 00476 buffer->_Xmin = 0; 00477 buffer->_Ymin = 0; 00478 buffer->_Xmax = buffer->Width; 00479 buffer->_Ymax = buffer->Height; 00480 00481 if (ctx->Scissor.Enabled) { 00482 if (ctx->Scissor.X > buffer->_Xmin) { 00483 buffer->_Xmin = ctx->Scissor.X; 00484 } 00485 if (ctx->Scissor.Y > buffer->_Ymin) { 00486 buffer->_Ymin = ctx->Scissor.Y; 00487 } 00488 if (ctx->Scissor.X + ctx->Scissor.Width < buffer->_Xmax) { 00489 buffer->_Xmax = ctx->Scissor.X + ctx->Scissor.Width; 00490 } 00491 if (ctx->Scissor.Y + ctx->Scissor.Height < buffer->_Ymax) { 00492 buffer->_Ymax = ctx->Scissor.Y + ctx->Scissor.Height; 00493 } 00494 /* finally, check for empty region */ 00495 if (buffer->_Xmin > buffer->_Xmax) { 00496 buffer->_Xmin = buffer->_Xmax; 00497 } 00498 if (buffer->_Ymin > buffer->_Ymax) { 00499 buffer->_Ymin = buffer->_Ymax; 00500 } 00501 } 00502 00503 ASSERT(buffer->_Xmin <= buffer->_Xmax); 00504 ASSERT(buffer->_Ymin <= buffer->_Ymax); 00505 } 00506 00507 00521 void 00522 _mesa_update_framebuffer_visual(struct gl_framebuffer *fb) 00523 { 00524 GLuint i; 00525 00526 _mesa_bzero(&fb->Visual, sizeof(fb->Visual)); 00527 fb->Visual.rgbMode = GL_TRUE; /* assume this */ 00528 00529 #if 0 /* this _might_ be needed */ 00530 if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { 00531 /* leave visual fields zero'd */ 00532 return; 00533 } 00534 #endif 00535 00536 /* find first RGB or CI renderbuffer */ 00537 for (i = 0; i < BUFFER_COUNT; i++) { 00538 if (fb->Attachment[i].Renderbuffer) { 00539 const struct gl_renderbuffer *rb = fb->Attachment[i].Renderbuffer; 00540 if (rb->_BaseFormat == GL_RGBA || rb->_BaseFormat == GL_RGB) { 00541 fb->Visual.redBits = rb->RedBits; 00542 fb->Visual.greenBits = rb->GreenBits; 00543 fb->Visual.blueBits = rb->BlueBits; 00544 fb->Visual.alphaBits = rb->AlphaBits; 00545 fb->Visual.rgbBits = fb->Visual.redBits 00546 + fb->Visual.greenBits + fb->Visual.blueBits; 00547 fb->Visual.floatMode = GL_FALSE; 00548 break; 00549 } 00550 else if (rb->_BaseFormat == GL_COLOR_INDEX) { 00551 fb->Visual.indexBits = rb->IndexBits; 00552 fb->Visual.rgbMode = GL_FALSE; 00553 break; 00554 } 00555 } 00556 } 00557 00558 if (fb->Attachment[BUFFER_DEPTH].Renderbuffer) { 00559 fb->Visual.haveDepthBuffer = GL_TRUE; 00560 fb->Visual.depthBits 00561 = fb->Attachment[BUFFER_DEPTH].Renderbuffer->DepthBits; 00562 } 00563 00564 if (fb->Attachment[BUFFER_STENCIL].Renderbuffer) { 00565 fb->Visual.haveStencilBuffer = GL_TRUE; 00566 fb->Visual.stencilBits 00567 = fb->Attachment[BUFFER_STENCIL].Renderbuffer->StencilBits; 00568 } 00569 00570 if (fb->Attachment[BUFFER_ACCUM].Renderbuffer) { 00571 fb->Visual.haveAccumBuffer = GL_TRUE; 00572 fb->Visual.accumRedBits 00573 = fb->Attachment[BUFFER_ACCUM].Renderbuffer->RedBits; 00574 fb->Visual.accumGreenBits 00575 = fb->Attachment[BUFFER_ACCUM].Renderbuffer->GreenBits; 00576 fb->Visual.accumBlueBits 00577 = fb->Attachment[BUFFER_ACCUM].Renderbuffer->BlueBits; 00578 fb->Visual.accumAlphaBits 00579 = fb->Attachment[BUFFER_ACCUM].Renderbuffer->AlphaBits; 00580 } 00581 00582 compute_depth_max(fb); 00583 } 00584 00585 00596 void 00597 _mesa_update_depth_buffer(GLcontext *ctx, 00598 struct gl_framebuffer *fb, 00599 GLuint attIndex) 00600 { 00601 struct gl_renderbuffer *depthRb; 00602 00603 /* only one possiblity for now */ 00604 ASSERT(attIndex == BUFFER_DEPTH); 00605 00606 depthRb = fb->Attachment[attIndex].Renderbuffer; 00607 00608 if (depthRb && depthRb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT) { 00609 /* The attached depth buffer is a GL_DEPTH_STENCIL renderbuffer */ 00610 if (!fb->_DepthBuffer 00611 || fb->_DepthBuffer->Wrapped != depthRb 00612 || fb->_DepthBuffer->_BaseFormat != GL_DEPTH_COMPONENT) { 00613 /* need to update wrapper */ 00614 struct gl_renderbuffer *wrapper 00615 = _mesa_new_z24_renderbuffer_wrapper(ctx, depthRb); 00616 _mesa_reference_renderbuffer(&fb->_DepthBuffer, wrapper); 00617 ASSERT(fb->_DepthBuffer->Wrapped == depthRb); 00618 } 00619 } 00620 else { 00621 /* depthRb may be null */ 00622 _mesa_reference_renderbuffer(&fb->_DepthBuffer, depthRb); 00623 } 00624 } 00625 00626 00637 void 00638 _mesa_update_stencil_buffer(GLcontext *ctx, 00639 struct gl_framebuffer *fb, 00640 GLuint attIndex) 00641 { 00642 struct gl_renderbuffer *stencilRb; 00643 00644 ASSERT(attIndex == BUFFER_DEPTH || 00645 attIndex == BUFFER_STENCIL); 00646 00647 stencilRb = fb->Attachment[attIndex].Renderbuffer; 00648 00649 if (stencilRb && stencilRb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT) { 00650 /* The attached stencil buffer is a GL_DEPTH_STENCIL renderbuffer */ 00651 if (!fb->_StencilBuffer 00652 || fb->_StencilBuffer->Wrapped != stencilRb 00653 || fb->_StencilBuffer->_BaseFormat != GL_STENCIL_INDEX) { 00654 /* need to update wrapper */ 00655 struct gl_renderbuffer *wrapper 00656 = _mesa_new_s8_renderbuffer_wrapper(ctx, stencilRb); 00657 _mesa_reference_renderbuffer(&fb->_StencilBuffer, wrapper); 00658 ASSERT(fb->_StencilBuffer->Wrapped == stencilRb); 00659 } 00660 } 00661 else { 00662 /* stencilRb may be null */ 00663 _mesa_reference_renderbuffer(&fb->_StencilBuffer, stencilRb); 00664 } 00665 } 00666 00667 00668 /* 00669 * Example DrawBuffers scenarios: 00670 * 00671 * 1. glDrawBuffer(GL_FRONT_AND_BACK), fixed-func or shader writes to 00672 * "gl_FragColor" or program writes to the "result.color" register: 00673 * 00674 * fragment color output renderbuffer 00675 * --------------------- --------------- 00676 * color[0] Front, Back 00677 * 00678 * 00679 * 2. glDrawBuffers(3, [GL_FRONT, GL_AUX0, GL_AUX1]), shader writes to 00680 * gl_FragData[i] or program writes to result.color[i] registers: 00681 * 00682 * fragment color output renderbuffer 00683 * --------------------- --------------- 00684 * color[0] Front 00685 * color[1] Aux0 00686 * color[3] Aux1 00687 * 00688 * 00689 * 3. glDrawBuffers(3, [GL_FRONT, GL_AUX0, GL_AUX1]) and shader writes to 00690 * gl_FragColor, or fixed function: 00691 * 00692 * fragment color output renderbuffer 00693 * --------------------- --------------- 00694 * color[0] Front, Aux0, Aux1 00695 * 00696 * 00697 * In either case, the list of renderbuffers is stored in the 00698 * framebuffer->_ColorDrawBuffers[] array and 00699 * framebuffer->_NumColorDrawBuffers indicates the number of buffers. 00700 * The renderer (like swrast) has to look at the current fragment shader 00701 * to see if it writes to gl_FragColor vs. gl_FragData[i] to determine 00702 * how to map color outputs to renderbuffers. 00703 * 00704 * Note that these two calls are equivalent (for fixed function fragment 00705 * shading anyway): 00706 * a) glDrawBuffer(GL_FRONT_AND_BACK); (assuming non-stereo framebuffer) 00707 * b) glDrawBuffers(2, [GL_FRONT_LEFT, GL_BACK_LEFT]); 00708 */ 00709 00710 00711 00712 00718 static void 00719 update_color_draw_buffers(GLcontext *ctx, struct gl_framebuffer *fb) 00720 { 00721 GLuint output; 00722 00723 /* set 0th buffer to NULL now in case _NumColorDrawBuffers is zero */ 00724 fb->_ColorDrawBuffers[0] = NULL; 00725 00726 for (output = 0; output < fb->_NumColorDrawBuffers; output++) { 00727 GLint buf = fb->_ColorDrawBufferIndexes[output]; 00728 if (buf >= 0) { 00729 fb->_ColorDrawBuffers[output] = fb->Attachment[buf].Renderbuffer; 00730 } 00731 else { 00732 fb->_ColorDrawBuffers[output] = NULL; 00733 } 00734 } 00735 } 00736 00737 00742 static void 00743 update_color_read_buffer(GLcontext *ctx, struct gl_framebuffer *fb) 00744 { 00745 (void) ctx; 00746 if (fb->_ColorReadBufferIndex == -1 || 00747 fb->DeletePending || 00748 fb->Width == 0 || 00749 fb->Height == 0) { 00750 fb->_ColorReadBuffer = NULL; /* legal! */ 00751 } 00752 else { 00753 ASSERT(fb->_ColorReadBufferIndex >= 0); 00754 ASSERT(fb->_ColorReadBufferIndex < BUFFER_COUNT); 00755 fb->_ColorReadBuffer 00756 = fb->Attachment[fb->_ColorReadBufferIndex].Renderbuffer; 00757 } 00758 } 00759 00760 00777 static void 00778 update_framebuffer(GLcontext *ctx, struct gl_framebuffer *fb) 00779 { 00780 if (fb->Name == 0) { 00781 /* This is a window-system framebuffer */ 00782 /* Need to update the FB's GL_DRAW_BUFFER state to match the 00783 * context state (GL_READ_BUFFER too). 00784 */ 00785 if (fb->ColorDrawBuffer[0] != ctx->Color.DrawBuffer[0]) { 00786 _mesa_drawbuffers(ctx, ctx->Const.MaxDrawBuffers, 00787 ctx->Color.DrawBuffer, NULL); 00788 } 00789 if (fb->ColorReadBuffer != ctx->Pixel.ReadBuffer) { 00790 00791 } 00792 } 00793 else { 00794 /* This is a user-created framebuffer. 00795 * Completeness only matters for user-created framebuffers. 00796 */ 00797 _mesa_test_framebuffer_completeness(ctx, fb); 00798 _mesa_update_framebuffer_visual(fb); 00799 } 00800 00801 /* Strictly speaking, we don't need to update the draw-state 00802 * if this FB is bound as ctx->ReadBuffer (and conversely, the 00803 * read-state if this FB is bound as ctx->DrawBuffer), but no 00804 * harm. 00805 */ 00806 update_color_draw_buffers(ctx, fb); 00807 update_color_read_buffer(ctx, fb); 00808 _mesa_update_depth_buffer(ctx, fb, BUFFER_DEPTH); 00809 _mesa_update_stencil_buffer(ctx, fb, BUFFER_STENCIL); 00810 00811 compute_depth_max(fb); 00812 } 00813 00814 00818 void 00819 _mesa_update_framebuffer(GLcontext *ctx) 00820 { 00821 struct gl_framebuffer *drawFb = ctx->DrawBuffer; 00822 struct gl_framebuffer *readFb = ctx->ReadBuffer; 00823 00824 update_framebuffer(ctx, drawFb); 00825 if (readFb != drawFb) 00826 update_framebuffer(ctx, readFb); 00827 } 00828 00829 00837 GLboolean 00838 _mesa_source_buffer_exists(GLcontext *ctx, GLenum format) 00839 { 00840 const struct gl_renderbuffer_attachment *att 00841 = ctx->ReadBuffer->Attachment; 00842 00843 if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { 00844 return GL_FALSE; 00845 } 00846 00847 switch (format) { 00848 case GL_COLOR: 00849 case GL_RED: 00850 case GL_GREEN: 00851 case GL_BLUE: 00852 case GL_ALPHA: 00853 case GL_LUMINANCE: 00854 case GL_LUMINANCE_ALPHA: 00855 case GL_INTENSITY: 00856 case GL_RGB: 00857 case GL_BGR: 00858 case GL_RGBA: 00859 case GL_BGRA: 00860 case GL_ABGR_EXT: 00861 case GL_COLOR_INDEX: 00862 if (ctx->ReadBuffer->_ColorReadBuffer == NULL) { 00863 return GL_FALSE; 00864 } 00865 /* XXX enable this post 6.5 release: 00866 ASSERT(ctx->ReadBuffer->_ColorReadBuffer->RedBits > 0 || 00867 ctx->ReadBuffer->_ColorReadBuffer->IndexBits > 0); 00868 */ 00869 break; 00870 case GL_DEPTH: 00871 case GL_DEPTH_COMPONENT: 00872 if (!att[BUFFER_DEPTH].Renderbuffer) { 00873 return GL_FALSE; 00874 } 00875 ASSERT(att[BUFFER_DEPTH].Renderbuffer->DepthBits > 0); 00876 break; 00877 case GL_STENCIL: 00878 case GL_STENCIL_INDEX: 00879 if (!att[BUFFER_STENCIL].Renderbuffer) { 00880 return GL_FALSE; 00881 } 00882 ASSERT(att[BUFFER_STENCIL].Renderbuffer->StencilBits > 0); 00883 break; 00884 case GL_DEPTH_STENCIL_EXT: 00885 if (!att[BUFFER_DEPTH].Renderbuffer || 00886 !att[BUFFER_STENCIL].Renderbuffer) { 00887 return GL_FALSE; 00888 } 00889 ASSERT(att[BUFFER_DEPTH].Renderbuffer->DepthBits > 0); 00890 ASSERT(att[BUFFER_STENCIL].Renderbuffer->StencilBits > 0); 00891 break; 00892 default: 00893 _mesa_problem(ctx, 00894 "Unexpected format 0x%x in _mesa_source_buffer_exists", 00895 format); 00896 return GL_FALSE; 00897 } 00898 00899 /* OK */ 00900 return GL_TRUE; 00901 } 00902 00903 00908 GLboolean 00909 _mesa_dest_buffer_exists(GLcontext *ctx, GLenum format) 00910 { 00911 const struct gl_renderbuffer_attachment *att 00912 = ctx->ReadBuffer->Attachment; 00913 00914 if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { 00915 return GL_FALSE; 00916 } 00917 00918 switch (format) { 00919 case GL_COLOR: 00920 case GL_RED: 00921 case GL_GREEN: 00922 case GL_BLUE: 00923 case GL_ALPHA: 00924 case GL_LUMINANCE: 00925 case GL_LUMINANCE_ALPHA: 00926 case GL_INTENSITY: 00927 case GL_RGB: 00928 case GL_BGR: 00929 case GL_RGBA: 00930 case GL_BGRA: 00931 case GL_ABGR_EXT: 00932 case GL_COLOR_INDEX: 00933 /* nothing special */ 00934 /* Could assert that colorbuffer has RedBits > 0 */ 00935 break; 00936 case GL_DEPTH: 00937 case GL_DEPTH_COMPONENT: 00938 if (!att[BUFFER_DEPTH].Renderbuffer) { 00939 return GL_FALSE; 00940 } 00941 ASSERT(att[BUFFER_DEPTH].Renderbuffer->DepthBits > 0); 00942 break; 00943 case GL_STENCIL: 00944 case GL_STENCIL_INDEX: 00945 if (!att[BUFFER_STENCIL].Renderbuffer) { 00946 return GL_FALSE; 00947 } 00948 ASSERT(att[BUFFER_STENCIL].Renderbuffer->StencilBits > 0); 00949 break; 00950 case GL_DEPTH_STENCIL_EXT: 00951 if (!att[BUFFER_DEPTH].Renderbuffer || 00952 !att[BUFFER_STENCIL].Renderbuffer) { 00953 return GL_FALSE; 00954 } 00955 ASSERT(att[BUFFER_DEPTH].Renderbuffer->DepthBits > 0); 00956 ASSERT(att[BUFFER_STENCIL].Renderbuffer->StencilBits > 0); 00957 break; 00958 default: 00959 _mesa_problem(ctx, 00960 "Unexpected format 0x%x in _mesa_source_buffer_exists", 00961 format); 00962 return GL_FALSE; 00963 } 00964 00965 /* OK */ 00966 return GL_TRUE; 00967 } Generated on Sun May 27 2012 04:20:17 for ReactOS by
1.7.6.1
|