1848b8605Smrg/* 2848b8605Smrg * Mesa 3-D graphics library 3848b8605Smrg * 4848b8605Smrg * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. 5848b8605Smrg * 6848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a 7848b8605Smrg * copy of this software and associated documentation files (the "Software"), 8848b8605Smrg * to deal in the Software without restriction, including without limitation 9848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the 11848b8605Smrg * Software is furnished to do so, subject to the following conditions: 12848b8605Smrg * 13848b8605Smrg * The above copyright notice and this permission notice shall be included 14848b8605Smrg * in all copies or substantial portions of the Software. 15848b8605Smrg * 16848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20848b8605Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21848b8605Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22848b8605Smrg * OTHER DEALINGS IN THE SOFTWARE. 23848b8605Smrg */ 24848b8605Smrg 25848b8605Smrg 26848b8605Smrg/** 27848b8605Smrg * Functions for allocating/managing framebuffers and renderbuffers. 28848b8605Smrg * Also, routines for reading/writing renderbuffer data as ubytes, 29848b8605Smrg * ushorts, uints, etc. 30848b8605Smrg */ 31848b8605Smrg 32b8e80941Smrg#include <stdio.h> 33848b8605Smrg#include "glheader.h" 34848b8605Smrg#include "imports.h" 35848b8605Smrg#include "blend.h" 36848b8605Smrg#include "buffers.h" 37848b8605Smrg#include "context.h" 38848b8605Smrg#include "enums.h" 39848b8605Smrg#include "formats.h" 40848b8605Smrg#include "macros.h" 41848b8605Smrg#include "mtypes.h" 42848b8605Smrg#include "fbobject.h" 43848b8605Smrg#include "framebuffer.h" 44848b8605Smrg#include "renderbuffer.h" 45848b8605Smrg#include "texobj.h" 46848b8605Smrg#include "glformats.h" 47b8e80941Smrg#include "state.h" 48848b8605Smrg 49848b8605Smrg 50848b8605Smrg 51848b8605Smrg/** 52848b8605Smrg * Compute/set the _DepthMax field for the given framebuffer. 53848b8605Smrg * This value depends on the Z buffer resolution. 54848b8605Smrg */ 55848b8605Smrgstatic void 56848b8605Smrgcompute_depth_max(struct gl_framebuffer *fb) 57848b8605Smrg{ 58848b8605Smrg if (fb->Visual.depthBits == 0) { 59848b8605Smrg /* Special case. Even if we don't have a depth buffer we need 60848b8605Smrg * good values for DepthMax for Z vertex transformation purposes 61848b8605Smrg * and for per-fragment fog computation. 62848b8605Smrg */ 63848b8605Smrg fb->_DepthMax = (1 << 16) - 1; 64848b8605Smrg } 65848b8605Smrg else if (fb->Visual.depthBits < 32) { 66848b8605Smrg fb->_DepthMax = (1 << fb->Visual.depthBits) - 1; 67848b8605Smrg } 68848b8605Smrg else { 69848b8605Smrg /* Special case since shift values greater than or equal to the 70848b8605Smrg * number of bits in the left hand expression's type are undefined. 71848b8605Smrg */ 72848b8605Smrg fb->_DepthMax = 0xffffffff; 73848b8605Smrg } 74848b8605Smrg fb->_DepthMaxF = (GLfloat) fb->_DepthMax; 75848b8605Smrg 76848b8605Smrg /* Minimum resolvable depth value, for polygon offset */ 77848b8605Smrg fb->_MRD = (GLfloat)1.0 / fb->_DepthMaxF; 78848b8605Smrg} 79848b8605Smrg 80848b8605Smrg/** 81848b8605Smrg * Create and initialize a gl_framebuffer object. 82848b8605Smrg * This is intended for creating _window_system_ framebuffers, not generic 83848b8605Smrg * framebuffer objects ala GL_EXT_framebuffer_object. 84848b8605Smrg * 85848b8605Smrg * \sa _mesa_new_framebuffer 86848b8605Smrg */ 87848b8605Smrgstruct gl_framebuffer * 88848b8605Smrg_mesa_create_framebuffer(const struct gl_config *visual) 89848b8605Smrg{ 90848b8605Smrg struct gl_framebuffer *fb = CALLOC_STRUCT(gl_framebuffer); 91848b8605Smrg assert(visual); 92848b8605Smrg if (fb) { 93848b8605Smrg _mesa_initialize_window_framebuffer(fb, visual); 94848b8605Smrg } 95848b8605Smrg return fb; 96848b8605Smrg} 97848b8605Smrg 98848b8605Smrg 99848b8605Smrg/** 100848b8605Smrg * Allocate a new gl_framebuffer object. 101848b8605Smrg * This is the default function for ctx->Driver.NewFramebuffer(). 102848b8605Smrg * This is for allocating user-created framebuffers, not window-system 103848b8605Smrg * framebuffers! 104848b8605Smrg * \sa _mesa_create_framebuffer 105848b8605Smrg */ 106848b8605Smrgstruct gl_framebuffer * 107848b8605Smrg_mesa_new_framebuffer(struct gl_context *ctx, GLuint name) 108848b8605Smrg{ 109848b8605Smrg struct gl_framebuffer *fb; 110848b8605Smrg (void) ctx; 111848b8605Smrg assert(name != 0); 112848b8605Smrg fb = CALLOC_STRUCT(gl_framebuffer); 113848b8605Smrg if (fb) { 114848b8605Smrg _mesa_initialize_user_framebuffer(fb, name); 115848b8605Smrg } 116848b8605Smrg return fb; 117848b8605Smrg} 118848b8605Smrg 119848b8605Smrg 120848b8605Smrg/** 121848b8605Smrg * Initialize a gl_framebuffer object. Typically used to initialize 122848b8605Smrg * window system-created framebuffers, not user-created framebuffers. 123848b8605Smrg * \sa _mesa_initialize_user_framebuffer 124848b8605Smrg */ 125848b8605Smrgvoid 126848b8605Smrg_mesa_initialize_window_framebuffer(struct gl_framebuffer *fb, 127848b8605Smrg const struct gl_config *visual) 128848b8605Smrg{ 129848b8605Smrg assert(fb); 130848b8605Smrg assert(visual); 131848b8605Smrg 132848b8605Smrg memset(fb, 0, sizeof(struct gl_framebuffer)); 133848b8605Smrg 134b8e80941Smrg simple_mtx_init(&fb->Mutex, mtx_plain); 135848b8605Smrg 136848b8605Smrg fb->RefCount = 1; 137848b8605Smrg 138848b8605Smrg /* save the visual */ 139848b8605Smrg fb->Visual = *visual; 140848b8605Smrg 141848b8605Smrg /* Init read/draw renderbuffer state */ 142848b8605Smrg if (visual->doubleBufferMode) { 143848b8605Smrg fb->_NumColorDrawBuffers = 1; 144848b8605Smrg fb->ColorDrawBuffer[0] = GL_BACK; 145848b8605Smrg fb->_ColorDrawBufferIndexes[0] = BUFFER_BACK_LEFT; 146848b8605Smrg fb->ColorReadBuffer = GL_BACK; 147848b8605Smrg fb->_ColorReadBufferIndex = BUFFER_BACK_LEFT; 148848b8605Smrg } 149848b8605Smrg else { 150848b8605Smrg fb->_NumColorDrawBuffers = 1; 151848b8605Smrg fb->ColorDrawBuffer[0] = GL_FRONT; 152848b8605Smrg fb->_ColorDrawBufferIndexes[0] = BUFFER_FRONT_LEFT; 153848b8605Smrg fb->ColorReadBuffer = GL_FRONT; 154848b8605Smrg fb->_ColorReadBufferIndex = BUFFER_FRONT_LEFT; 155848b8605Smrg } 156848b8605Smrg 157848b8605Smrg fb->Delete = _mesa_destroy_framebuffer; 158848b8605Smrg fb->_Status = GL_FRAMEBUFFER_COMPLETE_EXT; 159848b8605Smrg fb->_AllColorBuffersFixedPoint = !visual->floatMode; 160848b8605Smrg fb->_HasSNormOrFloatColorBuffer = visual->floatMode; 161b8e80941Smrg fb->_HasAttachments = true; 162b8e80941Smrg fb->FlipY = true; 163b8e80941Smrg 164b8e80941Smrg fb->SampleLocationTable = NULL; 165b8e80941Smrg fb->ProgrammableSampleLocations = 0; 166b8e80941Smrg fb->SampleLocationPixelGrid = 0; 167848b8605Smrg 168848b8605Smrg compute_depth_max(fb); 169848b8605Smrg} 170848b8605Smrg 171848b8605Smrg 172848b8605Smrg/** 173848b8605Smrg * Initialize a user-created gl_framebuffer object. 174848b8605Smrg * \sa _mesa_initialize_window_framebuffer 175848b8605Smrg */ 176848b8605Smrgvoid 177848b8605Smrg_mesa_initialize_user_framebuffer(struct gl_framebuffer *fb, GLuint name) 178848b8605Smrg{ 179848b8605Smrg assert(fb); 180848b8605Smrg assert(name); 181848b8605Smrg 182848b8605Smrg memset(fb, 0, sizeof(struct gl_framebuffer)); 183848b8605Smrg 184848b8605Smrg fb->Name = name; 185848b8605Smrg fb->RefCount = 1; 186848b8605Smrg fb->_NumColorDrawBuffers = 1; 187848b8605Smrg fb->ColorDrawBuffer[0] = GL_COLOR_ATTACHMENT0_EXT; 188848b8605Smrg fb->_ColorDrawBufferIndexes[0] = BUFFER_COLOR0; 189848b8605Smrg fb->ColorReadBuffer = GL_COLOR_ATTACHMENT0_EXT; 190848b8605Smrg fb->_ColorReadBufferIndex = BUFFER_COLOR0; 191b8e80941Smrg fb->SampleLocationTable = NULL; 192b8e80941Smrg fb->ProgrammableSampleLocations = 0; 193b8e80941Smrg fb->SampleLocationPixelGrid = 0; 194848b8605Smrg fb->Delete = _mesa_destroy_framebuffer; 195b8e80941Smrg simple_mtx_init(&fb->Mutex, mtx_plain); 196848b8605Smrg} 197848b8605Smrg 198848b8605Smrg 199848b8605Smrg/** 200848b8605Smrg * Deallocate buffer and everything attached to it. 201848b8605Smrg * Typically called via the gl_framebuffer->Delete() method. 202848b8605Smrg */ 203848b8605Smrgvoid 204848b8605Smrg_mesa_destroy_framebuffer(struct gl_framebuffer *fb) 205848b8605Smrg{ 206848b8605Smrg if (fb) { 207848b8605Smrg _mesa_free_framebuffer_data(fb); 208848b8605Smrg free(fb->Label); 209848b8605Smrg free(fb); 210848b8605Smrg } 211848b8605Smrg} 212848b8605Smrg 213848b8605Smrg 214848b8605Smrg/** 215848b8605Smrg * Free all the data hanging off the given gl_framebuffer, but don't free 216848b8605Smrg * the gl_framebuffer object itself. 217848b8605Smrg */ 218848b8605Smrgvoid 219848b8605Smrg_mesa_free_framebuffer_data(struct gl_framebuffer *fb) 220848b8605Smrg{ 221848b8605Smrg assert(fb); 222848b8605Smrg assert(fb->RefCount == 0); 223848b8605Smrg 224b8e80941Smrg simple_mtx_destroy(&fb->Mutex); 225848b8605Smrg 226b8e80941Smrg for (unsigned i = 0; i < BUFFER_COUNT; i++) { 227848b8605Smrg struct gl_renderbuffer_attachment *att = &fb->Attachment[i]; 228848b8605Smrg if (att->Renderbuffer) { 229848b8605Smrg _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); 230848b8605Smrg } 231848b8605Smrg if (att->Texture) { 232848b8605Smrg _mesa_reference_texobj(&att->Texture, NULL); 233848b8605Smrg } 234b8e80941Smrg assert(!att->Renderbuffer); 235b8e80941Smrg assert(!att->Texture); 236848b8605Smrg att->Type = GL_NONE; 237848b8605Smrg } 238b8e80941Smrg 239b8e80941Smrg free(fb->SampleLocationTable); 240b8e80941Smrg fb->SampleLocationTable = NULL; 241848b8605Smrg} 242848b8605Smrg 243848b8605Smrg 244848b8605Smrg/** 245848b8605Smrg * Set *ptr to point to fb, with refcounting and locking. 246848b8605Smrg * This is normally only called from the _mesa_reference_framebuffer() macro 247848b8605Smrg * when there's a real pointer change. 248848b8605Smrg */ 249848b8605Smrgvoid 250848b8605Smrg_mesa_reference_framebuffer_(struct gl_framebuffer **ptr, 251848b8605Smrg struct gl_framebuffer *fb) 252848b8605Smrg{ 253848b8605Smrg if (*ptr) { 254848b8605Smrg /* unreference old renderbuffer */ 255848b8605Smrg GLboolean deleteFlag = GL_FALSE; 256848b8605Smrg struct gl_framebuffer *oldFb = *ptr; 257848b8605Smrg 258b8e80941Smrg simple_mtx_lock(&oldFb->Mutex); 259b8e80941Smrg assert(oldFb->RefCount > 0); 260848b8605Smrg oldFb->RefCount--; 261848b8605Smrg deleteFlag = (oldFb->RefCount == 0); 262b8e80941Smrg simple_mtx_unlock(&oldFb->Mutex); 263b8e80941Smrg 264848b8605Smrg if (deleteFlag) 265848b8605Smrg oldFb->Delete(oldFb); 266848b8605Smrg 267848b8605Smrg *ptr = NULL; 268848b8605Smrg } 269848b8605Smrg 270848b8605Smrg if (fb) { 271b8e80941Smrg simple_mtx_lock(&fb->Mutex); 272848b8605Smrg fb->RefCount++; 273b8e80941Smrg simple_mtx_unlock(&fb->Mutex); 274848b8605Smrg *ptr = fb; 275848b8605Smrg } 276848b8605Smrg} 277848b8605Smrg 278848b8605Smrg 279848b8605Smrg/** 280848b8605Smrg * Resize the given framebuffer's renderbuffers to the new width and height. 281848b8605Smrg * This should only be used for window-system framebuffers, not 282848b8605Smrg * user-created renderbuffers (i.e. made with GL_EXT_framebuffer_object). 283b8e80941Smrg * This will typically be called directly from a device driver. 284848b8605Smrg * 285848b8605Smrg * \note it's possible for ctx to be null since a window can be resized 286848b8605Smrg * without a currently bound rendering context. 287848b8605Smrg */ 288848b8605Smrgvoid 289848b8605Smrg_mesa_resize_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb, 290848b8605Smrg GLuint width, GLuint height) 291848b8605Smrg{ 292848b8605Smrg /* XXX I think we could check if the size is not changing 293848b8605Smrg * and return early. 294848b8605Smrg */ 295848b8605Smrg 296848b8605Smrg /* Can only resize win-sys framebuffer objects */ 297848b8605Smrg assert(_mesa_is_winsys_fbo(fb)); 298848b8605Smrg 299b8e80941Smrg for (unsigned i = 0; i < BUFFER_COUNT; i++) { 300848b8605Smrg struct gl_renderbuffer_attachment *att = &fb->Attachment[i]; 301848b8605Smrg if (att->Type == GL_RENDERBUFFER_EXT && att->Renderbuffer) { 302848b8605Smrg struct gl_renderbuffer *rb = att->Renderbuffer; 303848b8605Smrg /* only resize if size is changing */ 304848b8605Smrg if (rb->Width != width || rb->Height != height) { 305848b8605Smrg if (rb->AllocStorage(ctx, rb, rb->InternalFormat, width, height)) { 306b8e80941Smrg assert(rb->Width == width); 307b8e80941Smrg assert(rb->Height == height); 308848b8605Smrg } 309848b8605Smrg else { 310848b8605Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "Resizing framebuffer"); 311848b8605Smrg /* no return */ 312848b8605Smrg } 313848b8605Smrg } 314848b8605Smrg } 315848b8605Smrg } 316848b8605Smrg 317848b8605Smrg fb->Width = width; 318848b8605Smrg fb->Height = height; 319848b8605Smrg 320848b8605Smrg if (ctx) { 321848b8605Smrg /* update scissor / window bounds */ 322b8e80941Smrg _mesa_update_draw_buffer_bounds(ctx, ctx->DrawBuffer); 323848b8605Smrg /* Signal new buffer state so that swrast will update its clipping 324848b8605Smrg * info (the CLIP_BIT flag). 325848b8605Smrg */ 326848b8605Smrg ctx->NewState |= _NEW_BUFFERS; 327848b8605Smrg } 328848b8605Smrg} 329848b8605Smrg 330848b8605Smrg/** 331b8e80941Smrg * Given a bounding box, intersect the bounding box with the scissor of 332b8e80941Smrg * a specified vieport. 333848b8605Smrg * 334848b8605Smrg * \param ctx GL context. 335848b8605Smrg * \param idx Index of the desired viewport 336848b8605Smrg * \param bbox Bounding box for the scissored viewport. Stored as xmin, 337848b8605Smrg * xmax, ymin, ymax. 338848b8605Smrg */ 339848b8605Smrgvoid 340b8e80941Smrg_mesa_intersect_scissor_bounding_box(const struct gl_context *ctx, 341b8e80941Smrg unsigned idx, int *bbox) 342848b8605Smrg{ 343848b8605Smrg if (ctx->Scissor.EnableFlags & (1u << idx)) { 344848b8605Smrg if (ctx->Scissor.ScissorArray[idx].X > bbox[0]) { 345848b8605Smrg bbox[0] = ctx->Scissor.ScissorArray[idx].X; 346848b8605Smrg } 347848b8605Smrg if (ctx->Scissor.ScissorArray[idx].Y > bbox[2]) { 348848b8605Smrg bbox[2] = ctx->Scissor.ScissorArray[idx].Y; 349848b8605Smrg } 350848b8605Smrg if (ctx->Scissor.ScissorArray[idx].X + ctx->Scissor.ScissorArray[idx].Width < bbox[1]) { 351848b8605Smrg bbox[1] = ctx->Scissor.ScissorArray[idx].X + ctx->Scissor.ScissorArray[idx].Width; 352848b8605Smrg } 353848b8605Smrg if (ctx->Scissor.ScissorArray[idx].Y + ctx->Scissor.ScissorArray[idx].Height < bbox[3]) { 354848b8605Smrg bbox[3] = ctx->Scissor.ScissorArray[idx].Y + ctx->Scissor.ScissorArray[idx].Height; 355848b8605Smrg } 356848b8605Smrg /* finally, check for empty region */ 357848b8605Smrg if (bbox[0] > bbox[1]) { 358848b8605Smrg bbox[0] = bbox[1]; 359848b8605Smrg } 360848b8605Smrg if (bbox[2] > bbox[3]) { 361848b8605Smrg bbox[2] = bbox[3]; 362848b8605Smrg } 363848b8605Smrg } 364b8e80941Smrg} 365848b8605Smrg 366b8e80941Smrg/** 367b8e80941Smrg * Calculate the inclusive bounding box for the scissor of a specific viewport 368b8e80941Smrg * 369b8e80941Smrg * \param ctx GL context. 370b8e80941Smrg * \param buffer Framebuffer to be checked against 371b8e80941Smrg * \param idx Index of the desired viewport 372b8e80941Smrg * \param bbox Bounding box for the scissored viewport. Stored as xmin, 373b8e80941Smrg * xmax, ymin, ymax. 374b8e80941Smrg * 375b8e80941Smrg * \warning This function assumes that the framebuffer dimensions are up to 376b8e80941Smrg * date. 377b8e80941Smrg * 378b8e80941Smrg * \sa _mesa_clip_to_region 379b8e80941Smrg */ 380b8e80941Smrgstatic void 381b8e80941Smrgscissor_bounding_box(const struct gl_context *ctx, 382b8e80941Smrg const struct gl_framebuffer *buffer, 383b8e80941Smrg unsigned idx, int *bbox) 384b8e80941Smrg{ 385b8e80941Smrg bbox[0] = 0; 386b8e80941Smrg bbox[2] = 0; 387b8e80941Smrg bbox[1] = buffer->Width; 388b8e80941Smrg bbox[3] = buffer->Height; 389b8e80941Smrg 390b8e80941Smrg _mesa_intersect_scissor_bounding_box(ctx, idx, bbox); 391b8e80941Smrg 392b8e80941Smrg assert(bbox[0] <= bbox[1]); 393b8e80941Smrg assert(bbox[2] <= bbox[3]); 394848b8605Smrg} 395848b8605Smrg 396848b8605Smrg/** 397848b8605Smrg * Update the context's current drawing buffer's Xmin, Xmax, Ymin, Ymax fields. 398848b8605Smrg * These values are computed from the buffer's width and height and 399848b8605Smrg * the scissor box, if it's enabled. 400848b8605Smrg * \param ctx the GL context. 401848b8605Smrg */ 402848b8605Smrgvoid 403b8e80941Smrg_mesa_update_draw_buffer_bounds(struct gl_context *ctx, 404b8e80941Smrg struct gl_framebuffer *buffer) 405848b8605Smrg{ 406848b8605Smrg int bbox[4]; 407848b8605Smrg 408848b8605Smrg if (!buffer) 409848b8605Smrg return; 410848b8605Smrg 411848b8605Smrg /* Default to the first scissor as that's always valid */ 412b8e80941Smrg scissor_bounding_box(ctx, buffer, 0, bbox); 413848b8605Smrg buffer->_Xmin = bbox[0]; 414848b8605Smrg buffer->_Ymin = bbox[2]; 415848b8605Smrg buffer->_Xmax = bbox[1]; 416848b8605Smrg buffer->_Ymax = bbox[3]; 417848b8605Smrg} 418848b8605Smrg 419848b8605Smrg 420848b8605Smrg/** 421848b8605Smrg * The glGet queries of the framebuffer red/green/blue size, stencil size, 422848b8605Smrg * etc. are satisfied by the fields of ctx->DrawBuffer->Visual. These can 423848b8605Smrg * change depending on the renderbuffer bindings. This function updates 424848b8605Smrg * the given framebuffer's Visual from the current renderbuffer bindings. 425848b8605Smrg * 426848b8605Smrg * This may apply to user-created framebuffers or window system framebuffers. 427848b8605Smrg * 428848b8605Smrg * Also note: ctx->DrawBuffer->Visual.depthBits might not equal 429848b8605Smrg * ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer.DepthBits. 430848b8605Smrg * The former one is used to convert floating point depth values into 431848b8605Smrg * integer Z values. 432848b8605Smrg */ 433848b8605Smrgvoid 434848b8605Smrg_mesa_update_framebuffer_visual(struct gl_context *ctx, 435848b8605Smrg struct gl_framebuffer *fb) 436848b8605Smrg{ 437848b8605Smrg memset(&fb->Visual, 0, sizeof(fb->Visual)); 438848b8605Smrg fb->Visual.rgbMode = GL_TRUE; /* assume this */ 439848b8605Smrg 440848b8605Smrg /* find first RGB renderbuffer */ 441b8e80941Smrg for (unsigned i = 0; i < BUFFER_COUNT; i++) { 442848b8605Smrg if (fb->Attachment[i].Renderbuffer) { 443848b8605Smrg const struct gl_renderbuffer *rb = fb->Attachment[i].Renderbuffer; 444848b8605Smrg const GLenum baseFormat = _mesa_get_format_base_format(rb->Format); 445848b8605Smrg const mesa_format fmt = rb->Format; 446848b8605Smrg 447848b8605Smrg /* Grab samples and sampleBuffers from any attachment point (assuming 448848b8605Smrg * the framebuffer is complete, we'll get the same answer from all 449848b8605Smrg * attachments). 450848b8605Smrg */ 451848b8605Smrg fb->Visual.samples = rb->NumSamples; 452848b8605Smrg fb->Visual.sampleBuffers = rb->NumSamples > 0 ? 1 : 0; 453848b8605Smrg 454848b8605Smrg if (_mesa_is_legal_color_format(ctx, baseFormat)) { 455848b8605Smrg fb->Visual.redBits = _mesa_get_format_bits(fmt, GL_RED_BITS); 456848b8605Smrg fb->Visual.greenBits = _mesa_get_format_bits(fmt, GL_GREEN_BITS); 457848b8605Smrg fb->Visual.blueBits = _mesa_get_format_bits(fmt, GL_BLUE_BITS); 458848b8605Smrg fb->Visual.alphaBits = _mesa_get_format_bits(fmt, GL_ALPHA_BITS); 459848b8605Smrg fb->Visual.rgbBits = fb->Visual.redBits 460848b8605Smrg + fb->Visual.greenBits + fb->Visual.blueBits; 461848b8605Smrg if (_mesa_get_format_color_encoding(fmt) == GL_SRGB) 462b8e80941Smrg fb->Visual.sRGBCapable = ctx->Extensions.EXT_sRGB; 463848b8605Smrg break; 464848b8605Smrg } 465848b8605Smrg } 466848b8605Smrg } 467848b8605Smrg 468848b8605Smrg fb->Visual.floatMode = GL_FALSE; 469b8e80941Smrg for (unsigned i = 0; i < BUFFER_COUNT; i++) { 470848b8605Smrg if (fb->Attachment[i].Renderbuffer) { 471848b8605Smrg const struct gl_renderbuffer *rb = fb->Attachment[i].Renderbuffer; 472848b8605Smrg const mesa_format fmt = rb->Format; 473848b8605Smrg 474848b8605Smrg if (_mesa_get_format_datatype(fmt) == GL_FLOAT) { 475848b8605Smrg fb->Visual.floatMode = GL_TRUE; 476848b8605Smrg break; 477848b8605Smrg } 478848b8605Smrg } 479848b8605Smrg } 480848b8605Smrg 481848b8605Smrg if (fb->Attachment[BUFFER_DEPTH].Renderbuffer) { 482848b8605Smrg const struct gl_renderbuffer *rb = 483848b8605Smrg fb->Attachment[BUFFER_DEPTH].Renderbuffer; 484848b8605Smrg const mesa_format fmt = rb->Format; 485848b8605Smrg fb->Visual.haveDepthBuffer = GL_TRUE; 486848b8605Smrg fb->Visual.depthBits = _mesa_get_format_bits(fmt, GL_DEPTH_BITS); 487848b8605Smrg } 488848b8605Smrg 489848b8605Smrg if (fb->Attachment[BUFFER_STENCIL].Renderbuffer) { 490848b8605Smrg const struct gl_renderbuffer *rb = 491848b8605Smrg fb->Attachment[BUFFER_STENCIL].Renderbuffer; 492848b8605Smrg const mesa_format fmt = rb->Format; 493848b8605Smrg fb->Visual.haveStencilBuffer = GL_TRUE; 494848b8605Smrg fb->Visual.stencilBits = _mesa_get_format_bits(fmt, GL_STENCIL_BITS); 495848b8605Smrg } 496848b8605Smrg 497848b8605Smrg if (fb->Attachment[BUFFER_ACCUM].Renderbuffer) { 498848b8605Smrg const struct gl_renderbuffer *rb = 499848b8605Smrg fb->Attachment[BUFFER_ACCUM].Renderbuffer; 500848b8605Smrg const mesa_format fmt = rb->Format; 501848b8605Smrg fb->Visual.haveAccumBuffer = GL_TRUE; 502848b8605Smrg fb->Visual.accumRedBits = _mesa_get_format_bits(fmt, GL_RED_BITS); 503848b8605Smrg fb->Visual.accumGreenBits = _mesa_get_format_bits(fmt, GL_GREEN_BITS); 504848b8605Smrg fb->Visual.accumBlueBits = _mesa_get_format_bits(fmt, GL_BLUE_BITS); 505848b8605Smrg fb->Visual.accumAlphaBits = _mesa_get_format_bits(fmt, GL_ALPHA_BITS); 506848b8605Smrg } 507848b8605Smrg 508848b8605Smrg compute_depth_max(fb); 509848b8605Smrg} 510848b8605Smrg 511848b8605Smrg 512848b8605Smrg/* 513848b8605Smrg * Example DrawBuffers scenarios: 514848b8605Smrg * 515848b8605Smrg * 1. glDrawBuffer(GL_FRONT_AND_BACK), fixed-func or shader writes to 516848b8605Smrg * "gl_FragColor" or program writes to the "result.color" register: 517848b8605Smrg * 518848b8605Smrg * fragment color output renderbuffer 519848b8605Smrg * --------------------- --------------- 520848b8605Smrg * color[0] Front, Back 521848b8605Smrg * 522848b8605Smrg * 523848b8605Smrg * 2. glDrawBuffers(3, [GL_FRONT, GL_AUX0, GL_AUX1]), shader writes to 524848b8605Smrg * gl_FragData[i] or program writes to result.color[i] registers: 525848b8605Smrg * 526848b8605Smrg * fragment color output renderbuffer 527848b8605Smrg * --------------------- --------------- 528848b8605Smrg * color[0] Front 529848b8605Smrg * color[1] Aux0 530848b8605Smrg * color[3] Aux1 531848b8605Smrg * 532848b8605Smrg * 533848b8605Smrg * 3. glDrawBuffers(3, [GL_FRONT, GL_AUX0, GL_AUX1]) and shader writes to 534848b8605Smrg * gl_FragColor, or fixed function: 535848b8605Smrg * 536848b8605Smrg * fragment color output renderbuffer 537848b8605Smrg * --------------------- --------------- 538848b8605Smrg * color[0] Front, Aux0, Aux1 539848b8605Smrg * 540848b8605Smrg * 541848b8605Smrg * In either case, the list of renderbuffers is stored in the 542848b8605Smrg * framebuffer->_ColorDrawBuffers[] array and 543848b8605Smrg * framebuffer->_NumColorDrawBuffers indicates the number of buffers. 544848b8605Smrg * The renderer (like swrast) has to look at the current fragment shader 545848b8605Smrg * to see if it writes to gl_FragColor vs. gl_FragData[i] to determine 546848b8605Smrg * how to map color outputs to renderbuffers. 547848b8605Smrg * 548848b8605Smrg * Note that these two calls are equivalent (for fixed function fragment 549848b8605Smrg * shading anyway): 550848b8605Smrg * a) glDrawBuffer(GL_FRONT_AND_BACK); (assuming non-stereo framebuffer) 551848b8605Smrg * b) glDrawBuffers(2, [GL_FRONT_LEFT, GL_BACK_LEFT]); 552848b8605Smrg */ 553848b8605Smrg 554848b8605Smrg 555848b8605Smrg 556848b8605Smrg 557848b8605Smrg/** 558848b8605Smrg * Update the (derived) list of color drawing renderbuffer pointers. 559848b8605Smrg * Later, when we're rendering we'll loop from 0 to _NumColorDrawBuffers 560848b8605Smrg * writing colors. 561848b8605Smrg */ 562848b8605Smrgstatic void 563b8e80941Smrgupdate_color_draw_buffers(struct gl_framebuffer *fb) 564848b8605Smrg{ 565848b8605Smrg GLuint output; 566848b8605Smrg 567848b8605Smrg /* set 0th buffer to NULL now in case _NumColorDrawBuffers is zero */ 568848b8605Smrg fb->_ColorDrawBuffers[0] = NULL; 569848b8605Smrg 570848b8605Smrg for (output = 0; output < fb->_NumColorDrawBuffers; output++) { 571b8e80941Smrg gl_buffer_index buf = fb->_ColorDrawBufferIndexes[output]; 572b8e80941Smrg if (buf != BUFFER_NONE) { 573848b8605Smrg fb->_ColorDrawBuffers[output] = fb->Attachment[buf].Renderbuffer; 574848b8605Smrg } 575848b8605Smrg else { 576848b8605Smrg fb->_ColorDrawBuffers[output] = NULL; 577848b8605Smrg } 578848b8605Smrg } 579848b8605Smrg} 580848b8605Smrg 581848b8605Smrg 582848b8605Smrg/** 583848b8605Smrg * Update the (derived) color read renderbuffer pointer. 584848b8605Smrg * Unlike the DrawBuffer, we can only read from one (or zero) color buffers. 585848b8605Smrg */ 586848b8605Smrgstatic void 587b8e80941Smrgupdate_color_read_buffer(struct gl_framebuffer *fb) 588848b8605Smrg{ 589b8e80941Smrg if (fb->_ColorReadBufferIndex == BUFFER_NONE || 590848b8605Smrg fb->DeletePending || 591848b8605Smrg fb->Width == 0 || 592848b8605Smrg fb->Height == 0) { 593848b8605Smrg fb->_ColorReadBuffer = NULL; /* legal! */ 594848b8605Smrg } 595848b8605Smrg else { 596b8e80941Smrg assert(fb->_ColorReadBufferIndex >= 0); 597b8e80941Smrg assert(fb->_ColorReadBufferIndex < BUFFER_COUNT); 598848b8605Smrg fb->_ColorReadBuffer 599848b8605Smrg = fb->Attachment[fb->_ColorReadBufferIndex].Renderbuffer; 600848b8605Smrg } 601848b8605Smrg} 602848b8605Smrg 603848b8605Smrg 604848b8605Smrg/** 605848b8605Smrg * Update a gl_framebuffer's derived state. 606848b8605Smrg * 607848b8605Smrg * Specifically, update these framebuffer fields: 608848b8605Smrg * _ColorDrawBuffers 609848b8605Smrg * _NumColorDrawBuffers 610848b8605Smrg * _ColorReadBuffer 611848b8605Smrg * 612848b8605Smrg * If the framebuffer is user-created, make sure it's complete. 613848b8605Smrg * 614848b8605Smrg * The following functions (at least) can effect framebuffer state: 615848b8605Smrg * glReadBuffer, glDrawBuffer, glDrawBuffersARB, glFramebufferRenderbufferEXT, 616848b8605Smrg * glRenderbufferStorageEXT. 617848b8605Smrg */ 618848b8605Smrgstatic void 619848b8605Smrgupdate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb) 620848b8605Smrg{ 621848b8605Smrg if (_mesa_is_winsys_fbo(fb)) { 622848b8605Smrg /* This is a window-system framebuffer */ 623848b8605Smrg /* Need to update the FB's GL_DRAW_BUFFER state to match the 624848b8605Smrg * context state (GL_READ_BUFFER too). 625848b8605Smrg */ 626848b8605Smrg if (fb->ColorDrawBuffer[0] != ctx->Color.DrawBuffer[0]) { 627b8e80941Smrg _mesa_drawbuffers(ctx, fb, ctx->Const.MaxDrawBuffers, 628848b8605Smrg ctx->Color.DrawBuffer, NULL); 629848b8605Smrg } 630b8e80941Smrg 631b8e80941Smrg /* Call device driver function if fb is the bound draw buffer. */ 632b8e80941Smrg if (fb == ctx->DrawBuffer) { 633b8e80941Smrg if (ctx->Driver.DrawBufferAllocate) 634b8e80941Smrg ctx->Driver.DrawBufferAllocate(ctx); 635b8e80941Smrg } 636848b8605Smrg } 637848b8605Smrg else { 638848b8605Smrg /* This is a user-created framebuffer. 639848b8605Smrg * Completeness only matters for user-created framebuffers. 640848b8605Smrg */ 641848b8605Smrg if (fb->_Status != GL_FRAMEBUFFER_COMPLETE) { 642848b8605Smrg _mesa_test_framebuffer_completeness(ctx, fb); 643848b8605Smrg } 644848b8605Smrg } 645848b8605Smrg 646848b8605Smrg /* Strictly speaking, we don't need to update the draw-state 647848b8605Smrg * if this FB is bound as ctx->ReadBuffer (and conversely, the 648848b8605Smrg * read-state if this FB is bound as ctx->DrawBuffer), but no 649848b8605Smrg * harm. 650848b8605Smrg */ 651b8e80941Smrg update_color_draw_buffers(fb); 652b8e80941Smrg update_color_read_buffer(fb); 653848b8605Smrg 654848b8605Smrg compute_depth_max(fb); 655848b8605Smrg} 656848b8605Smrg 657848b8605Smrg 658848b8605Smrg/** 659b8e80941Smrg * Update state related to the draw/read framebuffers. 660848b8605Smrg */ 661848b8605Smrgvoid 662b8e80941Smrg_mesa_update_framebuffer(struct gl_context *ctx, 663b8e80941Smrg struct gl_framebuffer *readFb, 664b8e80941Smrg struct gl_framebuffer *drawFb) 665848b8605Smrg{ 666848b8605Smrg assert(ctx); 667848b8605Smrg 668848b8605Smrg update_framebuffer(ctx, drawFb); 669848b8605Smrg if (readFb != drawFb) 670848b8605Smrg update_framebuffer(ctx, readFb); 671848b8605Smrg 672b8e80941Smrg _mesa_update_clamp_vertex_color(ctx, drawFb); 673b8e80941Smrg _mesa_update_clamp_fragment_color(ctx, drawFb); 674848b8605Smrg} 675848b8605Smrg 676848b8605Smrg 677848b8605Smrg/** 678848b8605Smrg * Check if the renderbuffer for a read/draw operation exists. 679848b8605Smrg * \param format a basic image format such as GL_RGB, GL_RGBA, GL_ALPHA, 680848b8605Smrg * GL_DEPTH_COMPONENT, etc. or GL_COLOR, GL_DEPTH, GL_STENCIL. 681848b8605Smrg * \param reading if TRUE, we're going to read from the buffer, 682848b8605Smrg if FALSE, we're going to write to the buffer. 683848b8605Smrg * \return GL_TRUE if buffer exists, GL_FALSE otherwise 684848b8605Smrg */ 685848b8605Smrgstatic GLboolean 686848b8605Smrgrenderbuffer_exists(struct gl_context *ctx, 687848b8605Smrg struct gl_framebuffer *fb, 688848b8605Smrg GLenum format, 689848b8605Smrg GLboolean reading) 690848b8605Smrg{ 691848b8605Smrg const struct gl_renderbuffer_attachment *att = fb->Attachment; 692848b8605Smrg 693848b8605Smrg /* If we don't know the framebuffer status, update it now */ 694848b8605Smrg if (fb->_Status == 0) { 695848b8605Smrg _mesa_test_framebuffer_completeness(ctx, fb); 696848b8605Smrg } 697848b8605Smrg 698848b8605Smrg if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { 699848b8605Smrg return GL_FALSE; 700848b8605Smrg } 701848b8605Smrg 702848b8605Smrg switch (format) { 703848b8605Smrg case GL_COLOR: 704848b8605Smrg case GL_RED: 705848b8605Smrg case GL_GREEN: 706848b8605Smrg case GL_BLUE: 707848b8605Smrg case GL_ALPHA: 708848b8605Smrg case GL_LUMINANCE: 709848b8605Smrg case GL_LUMINANCE_ALPHA: 710848b8605Smrg case GL_INTENSITY: 711848b8605Smrg case GL_RG: 712848b8605Smrg case GL_RGB: 713848b8605Smrg case GL_BGR: 714848b8605Smrg case GL_RGBA: 715848b8605Smrg case GL_BGRA: 716848b8605Smrg case GL_ABGR_EXT: 717848b8605Smrg case GL_RED_INTEGER_EXT: 718848b8605Smrg case GL_RG_INTEGER: 719848b8605Smrg case GL_GREEN_INTEGER_EXT: 720848b8605Smrg case GL_BLUE_INTEGER_EXT: 721848b8605Smrg case GL_ALPHA_INTEGER_EXT: 722848b8605Smrg case GL_RGB_INTEGER_EXT: 723848b8605Smrg case GL_RGBA_INTEGER_EXT: 724848b8605Smrg case GL_BGR_INTEGER_EXT: 725848b8605Smrg case GL_BGRA_INTEGER_EXT: 726848b8605Smrg case GL_LUMINANCE_INTEGER_EXT: 727848b8605Smrg case GL_LUMINANCE_ALPHA_INTEGER_EXT: 728848b8605Smrg if (reading) { 729848b8605Smrg /* about to read from a color buffer */ 730848b8605Smrg const struct gl_renderbuffer *readBuf = fb->_ColorReadBuffer; 731848b8605Smrg if (!readBuf) { 732848b8605Smrg return GL_FALSE; 733848b8605Smrg } 734b8e80941Smrg assert(_mesa_get_format_bits(readBuf->Format, GL_RED_BITS) > 0 || 735848b8605Smrg _mesa_get_format_bits(readBuf->Format, GL_ALPHA_BITS) > 0 || 736848b8605Smrg _mesa_get_format_bits(readBuf->Format, GL_TEXTURE_LUMINANCE_SIZE) > 0 || 737848b8605Smrg _mesa_get_format_bits(readBuf->Format, GL_TEXTURE_INTENSITY_SIZE) > 0 || 738848b8605Smrg _mesa_get_format_bits(readBuf->Format, GL_INDEX_BITS) > 0); 739848b8605Smrg } 740848b8605Smrg else { 741848b8605Smrg /* about to draw to zero or more color buffers (none is OK) */ 742848b8605Smrg return GL_TRUE; 743848b8605Smrg } 744848b8605Smrg break; 745848b8605Smrg case GL_DEPTH: 746848b8605Smrg case GL_DEPTH_COMPONENT: 747848b8605Smrg if (att[BUFFER_DEPTH].Type == GL_NONE) { 748848b8605Smrg return GL_FALSE; 749848b8605Smrg } 750848b8605Smrg break; 751848b8605Smrg case GL_STENCIL: 752848b8605Smrg case GL_STENCIL_INDEX: 753848b8605Smrg if (att[BUFFER_STENCIL].Type == GL_NONE) { 754848b8605Smrg return GL_FALSE; 755848b8605Smrg } 756848b8605Smrg break; 757848b8605Smrg case GL_DEPTH_STENCIL_EXT: 758848b8605Smrg if (att[BUFFER_DEPTH].Type == GL_NONE || 759848b8605Smrg att[BUFFER_STENCIL].Type == GL_NONE) { 760848b8605Smrg return GL_FALSE; 761848b8605Smrg } 762848b8605Smrg break; 763848b8605Smrg default: 764848b8605Smrg _mesa_problem(ctx, 765848b8605Smrg "Unexpected format 0x%x in renderbuffer_exists", 766848b8605Smrg format); 767848b8605Smrg return GL_FALSE; 768848b8605Smrg } 769848b8605Smrg 770848b8605Smrg /* OK */ 771848b8605Smrg return GL_TRUE; 772848b8605Smrg} 773848b8605Smrg 774848b8605Smrg 775848b8605Smrg/** 776848b8605Smrg * Check if the renderbuffer for a read operation (glReadPixels, glCopyPixels, 777848b8605Smrg * glCopyTex[Sub]Image, etc) exists. 778848b8605Smrg * \param format a basic image format such as GL_RGB, GL_RGBA, GL_ALPHA, 779848b8605Smrg * GL_DEPTH_COMPONENT, etc. or GL_COLOR, GL_DEPTH, GL_STENCIL. 780848b8605Smrg * \return GL_TRUE if buffer exists, GL_FALSE otherwise 781848b8605Smrg */ 782848b8605SmrgGLboolean 783848b8605Smrg_mesa_source_buffer_exists(struct gl_context *ctx, GLenum format) 784848b8605Smrg{ 785848b8605Smrg return renderbuffer_exists(ctx, ctx->ReadBuffer, format, GL_TRUE); 786848b8605Smrg} 787848b8605Smrg 788848b8605Smrg 789848b8605Smrg/** 790848b8605Smrg * As above, but for drawing operations. 791848b8605Smrg */ 792848b8605SmrgGLboolean 793848b8605Smrg_mesa_dest_buffer_exists(struct gl_context *ctx, GLenum format) 794848b8605Smrg{ 795848b8605Smrg return renderbuffer_exists(ctx, ctx->DrawBuffer, format, GL_FALSE); 796848b8605Smrg} 797848b8605Smrg 798848b8605Smrg 799848b8605Smrg/** 800b8e80941Smrg * Used to answer the GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES queries (using 801b8e80941Smrg * GetIntegerv, GetFramebufferParameteriv, etc) 802b8e80941Smrg * 803b8e80941Smrg * If @fb is NULL, the method returns the value for the current bound 804b8e80941Smrg * framebuffer. 805848b8605Smrg */ 806848b8605SmrgGLenum 807b8e80941Smrg_mesa_get_color_read_format(struct gl_context *ctx, 808b8e80941Smrg struct gl_framebuffer *fb, 809b8e80941Smrg const char *caller) 810848b8605Smrg{ 811b8e80941Smrg if (ctx->NewState) 812b8e80941Smrg _mesa_update_state(ctx); 813b8e80941Smrg 814b8e80941Smrg if (fb == NULL) 815b8e80941Smrg fb = ctx->ReadBuffer; 816b8e80941Smrg 817b8e80941Smrg if (!fb || !fb->_ColorReadBuffer) { 818b8e80941Smrg /* 819b8e80941Smrg * From OpenGL 4.5 spec, section 18.2.2 "ReadPixels": 820b8e80941Smrg * 821b8e80941Smrg * "An INVALID_OPERATION error is generated by GetIntegerv if pname 822b8e80941Smrg * is IMPLEMENTATION_COLOR_READ_FORMAT or IMPLEMENTATION_COLOR_- 823b8e80941Smrg * READ_TYPE and any of: 824b8e80941Smrg * * the read framebuffer is not framebuffer complete. 825b8e80941Smrg * * the read framebuffer is a framebuffer object, and the selected 826b8e80941Smrg * read buffer (see section 18.2.1) has no image attached. 827b8e80941Smrg * * the selected read buffer is NONE." 828b8e80941Smrg * 829b8e80941Smrg * There is not equivalent quote for GetFramebufferParameteriv or 830b8e80941Smrg * GetNamedFramebufferParameteriv, but from section 9.2.3 "Framebuffer 831b8e80941Smrg * Object Queries": 832b8e80941Smrg * 833b8e80941Smrg * "Values of framebuffer-dependent state are identical to those that 834b8e80941Smrg * would be obtained were the framebuffer object bound and queried 835b8e80941Smrg * using the simple state queries in that table." 836b8e80941Smrg * 837b8e80941Smrg * Where "using the simple state queries" refer to use GetIntegerv. So 838b8e80941Smrg * we will assume that on that situation the same error should be 839b8e80941Smrg * triggered too. 840848b8605Smrg */ 841848b8605Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 842b8e80941Smrg "%s(GL_IMPLEMENTATION_COLOR_READ_FORMAT: no GL_READ_BUFFER)", 843b8e80941Smrg caller); 844848b8605Smrg return GL_NONE; 845848b8605Smrg } 846848b8605Smrg else { 847b8e80941Smrg const mesa_format format = fb->_ColorReadBuffer->Format; 848848b8605Smrg 849b8e80941Smrg switch (format) { 850b8e80941Smrg case MESA_FORMAT_RGBA_UINT8: 851b8e80941Smrg return GL_RGBA_INTEGER; 852b8e80941Smrg case MESA_FORMAT_B8G8R8A8_UNORM: 853848b8605Smrg return GL_BGRA; 854b8e80941Smrg case MESA_FORMAT_B5G6R5_UNORM: 855b8e80941Smrg case MESA_FORMAT_R11G11B10_FLOAT: 856b8e80941Smrg return GL_RGB; 857b8e80941Smrg case MESA_FORMAT_RG_FLOAT32: 858b8e80941Smrg case MESA_FORMAT_RG_FLOAT16: 859b8e80941Smrg case MESA_FORMAT_R8G8_UNORM: 860b8e80941Smrg case MESA_FORMAT_R8G8_SNORM: 861b8e80941Smrg return GL_RG; 862b8e80941Smrg case MESA_FORMAT_RG_SINT32: 863b8e80941Smrg case MESA_FORMAT_RG_UINT32: 864b8e80941Smrg case MESA_FORMAT_RG_SINT16: 865b8e80941Smrg case MESA_FORMAT_RG_UINT16: 866b8e80941Smrg case MESA_FORMAT_RG_SINT8: 867b8e80941Smrg case MESA_FORMAT_RG_UINT8: 868b8e80941Smrg return GL_RG_INTEGER; 869b8e80941Smrg case MESA_FORMAT_R_FLOAT32: 870b8e80941Smrg case MESA_FORMAT_R_FLOAT16: 871b8e80941Smrg case MESA_FORMAT_R_UNORM16: 872b8e80941Smrg case MESA_FORMAT_R_UNORM8: 873b8e80941Smrg case MESA_FORMAT_R_SNORM16: 874b8e80941Smrg case MESA_FORMAT_R_SNORM8: 875b8e80941Smrg return GL_RED; 876b8e80941Smrg case MESA_FORMAT_R_SINT32: 877b8e80941Smrg case MESA_FORMAT_R_UINT32: 878b8e80941Smrg case MESA_FORMAT_R_SINT16: 879b8e80941Smrg case MESA_FORMAT_R_UINT16: 880b8e80941Smrg case MESA_FORMAT_R_SINT8: 881b8e80941Smrg case MESA_FORMAT_R_UINT8: 882b8e80941Smrg return GL_RED_INTEGER; 883b8e80941Smrg default: 884b8e80941Smrg break; 885b8e80941Smrg } 886848b8605Smrg 887b8e80941Smrg if (_mesa_is_format_integer(format)) 888848b8605Smrg return GL_RGBA_INTEGER; 889b8e80941Smrg else 890848b8605Smrg return GL_RGBA; 891848b8605Smrg } 892848b8605Smrg} 893848b8605Smrg 894848b8605Smrg 895848b8605Smrg/** 896b8e80941Smrg * Used to answer the GL_IMPLEMENTATION_COLOR_READ_TYPE_OES queries (using 897b8e80941Smrg * GetIntegerv, GetFramebufferParameteriv, etc) 898b8e80941Smrg * 899b8e80941Smrg * If @fb is NULL, the method returns the value for the current bound 900b8e80941Smrg * framebuffer. 901848b8605Smrg */ 902848b8605SmrgGLenum 903b8e80941Smrg_mesa_get_color_read_type(struct gl_context *ctx, 904b8e80941Smrg struct gl_framebuffer *fb, 905b8e80941Smrg const char *caller) 906848b8605Smrg{ 907b8e80941Smrg if (ctx->NewState) 908b8e80941Smrg _mesa_update_state(ctx); 909b8e80941Smrg 910b8e80941Smrg if (fb == NULL) 911b8e80941Smrg fb = ctx->ReadBuffer; 912b8e80941Smrg 913b8e80941Smrg if (!fb || !fb->_ColorReadBuffer) { 914b8e80941Smrg /* 915b8e80941Smrg * See comment on _mesa_get_color_read_format 916848b8605Smrg */ 917848b8605Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 918b8e80941Smrg "%s(GL_IMPLEMENTATION_COLOR_READ_TYPE: no GL_READ_BUFFER)", 919b8e80941Smrg caller); 920848b8605Smrg return GL_NONE; 921848b8605Smrg } 922848b8605Smrg else { 923b8e80941Smrg const mesa_format format = fb->_ColorReadBuffer->Format; 924b8e80941Smrg GLenum data_type; 925b8e80941Smrg GLuint comps; 926b8e80941Smrg 927b8e80941Smrg _mesa_uncompressed_format_to_type_and_comps(format, &data_type, &comps); 928b8e80941Smrg 929b8e80941Smrg return data_type; 930848b8605Smrg } 931848b8605Smrg} 932848b8605Smrg 933848b8605Smrg 934848b8605Smrg/** 935848b8605Smrg * Returns the read renderbuffer for the specified format. 936848b8605Smrg */ 937848b8605Smrgstruct gl_renderbuffer * 938848b8605Smrg_mesa_get_read_renderbuffer_for_format(const struct gl_context *ctx, 939848b8605Smrg GLenum format) 940848b8605Smrg{ 941848b8605Smrg const struct gl_framebuffer *rfb = ctx->ReadBuffer; 942848b8605Smrg 943848b8605Smrg if (_mesa_is_color_format(format)) { 944848b8605Smrg return rfb->Attachment[rfb->_ColorReadBufferIndex].Renderbuffer; 945848b8605Smrg } else if (_mesa_is_depth_format(format) || 946848b8605Smrg _mesa_is_depthstencil_format(format)) { 947848b8605Smrg return rfb->Attachment[BUFFER_DEPTH].Renderbuffer; 948848b8605Smrg } else { 949848b8605Smrg return rfb->Attachment[BUFFER_STENCIL].Renderbuffer; 950848b8605Smrg } 951848b8605Smrg} 952848b8605Smrg 953848b8605Smrg 954848b8605Smrg/** 955848b8605Smrg * Print framebuffer info to stderr, for debugging. 956848b8605Smrg */ 957848b8605Smrgvoid 958848b8605Smrg_mesa_print_framebuffer(const struct gl_framebuffer *fb) 959848b8605Smrg{ 960848b8605Smrg fprintf(stderr, "Mesa Framebuffer %u at %p\n", fb->Name, (void *) fb); 961848b8605Smrg fprintf(stderr, " Size: %u x %u Status: %s\n", fb->Width, fb->Height, 962b8e80941Smrg _mesa_enum_to_string(fb->_Status)); 963848b8605Smrg fprintf(stderr, " Attachments:\n"); 964848b8605Smrg 965b8e80941Smrg for (unsigned i = 0; i < BUFFER_COUNT; i++) { 966848b8605Smrg const struct gl_renderbuffer_attachment *att = &fb->Attachment[i]; 967848b8605Smrg if (att->Type == GL_TEXTURE) { 968848b8605Smrg const struct gl_texture_image *texImage = att->Renderbuffer->TexImage; 969848b8605Smrg fprintf(stderr, 970848b8605Smrg " %2d: Texture %u, level %u, face %u, slice %u, complete %d\n", 971848b8605Smrg i, att->Texture->Name, att->TextureLevel, att->CubeMapFace, 972848b8605Smrg att->Zoffset, att->Complete); 973848b8605Smrg fprintf(stderr, " Size: %u x %u x %u Format %s\n", 974848b8605Smrg texImage->Width, texImage->Height, texImage->Depth, 975848b8605Smrg _mesa_get_format_name(texImage->TexFormat)); 976848b8605Smrg } 977848b8605Smrg else if (att->Type == GL_RENDERBUFFER) { 978848b8605Smrg fprintf(stderr, " %2d: Renderbuffer %u, complete %d\n", 979848b8605Smrg i, att->Renderbuffer->Name, att->Complete); 980848b8605Smrg fprintf(stderr, " Size: %u x %u Format %s\n", 981848b8605Smrg att->Renderbuffer->Width, att->Renderbuffer->Height, 982848b8605Smrg _mesa_get_format_name(att->Renderbuffer->Format)); 983848b8605Smrg } 984848b8605Smrg else { 985848b8605Smrg fprintf(stderr, " %2d: none\n", i); 986848b8605Smrg } 987848b8605Smrg } 988848b8605Smrg} 989b8e80941Smrg 990b8e80941Smrgbool 991b8e80941Smrg_mesa_is_front_buffer_reading(const struct gl_framebuffer *fb) 992b8e80941Smrg{ 993b8e80941Smrg if (!fb || _mesa_is_user_fbo(fb)) 994b8e80941Smrg return false; 995b8e80941Smrg 996b8e80941Smrg return fb->_ColorReadBufferIndex == BUFFER_FRONT_LEFT; 997b8e80941Smrg} 998b8e80941Smrg 999b8e80941Smrgbool 1000b8e80941Smrg_mesa_is_front_buffer_drawing(const struct gl_framebuffer *fb) 1001b8e80941Smrg{ 1002b8e80941Smrg if (!fb || _mesa_is_user_fbo(fb)) 1003b8e80941Smrg return false; 1004b8e80941Smrg 1005b8e80941Smrg return (fb->_NumColorDrawBuffers >= 1 && 1006b8e80941Smrg fb->_ColorDrawBufferIndexes[0] == BUFFER_FRONT_LEFT); 1007b8e80941Smrg} 1008b8e80941Smrg 1009b8e80941Smrgstatic inline GLuint 1010b8e80941Smrg_mesa_geometric_nonvalidated_samples(const struct gl_framebuffer *buffer) 1011b8e80941Smrg{ 1012b8e80941Smrg return buffer->_HasAttachments ? 1013b8e80941Smrg buffer->Visual.samples : 1014b8e80941Smrg buffer->DefaultGeometry.NumSamples; 1015b8e80941Smrg} 1016b8e80941Smrg 1017b8e80941Smrgbool 1018b8e80941Smrg_mesa_is_multisample_enabled(const struct gl_context *ctx) 1019b8e80941Smrg{ 1020b8e80941Smrg /* The sample count may not be validated by the driver, but when it is set, 1021b8e80941Smrg * we know that is in a valid range and no driver should ever validate a 1022b8e80941Smrg * multisampled framebuffer to non-multisampled and vice-versa. 1023b8e80941Smrg */ 1024b8e80941Smrg return ctx->Multisample.Enabled && 1025b8e80941Smrg ctx->DrawBuffer && 1026b8e80941Smrg _mesa_geometric_nonvalidated_samples(ctx->DrawBuffer) >= 1; 1027b8e80941Smrg} 1028b8e80941Smrg 1029b8e80941Smrg/** 1030b8e80941Smrg * Is alpha testing enabled and applicable to the currently bound 1031b8e80941Smrg * framebuffer? 1032b8e80941Smrg */ 1033b8e80941Smrgbool 1034b8e80941Smrg_mesa_is_alpha_test_enabled(const struct gl_context *ctx) 1035b8e80941Smrg{ 1036b8e80941Smrg bool buffer0_is_integer = ctx->DrawBuffer->_IntegerBuffers & 0x1; 1037b8e80941Smrg return (ctx->Color.AlphaEnabled && !buffer0_is_integer); 1038b8e80941Smrg} 1039b8e80941Smrg 1040b8e80941Smrg/** 1041b8e80941Smrg * Is alpha to coverage enabled and applicable to the currently bound 1042b8e80941Smrg * framebuffer? 1043b8e80941Smrg */ 1044b8e80941Smrgbool 1045b8e80941Smrg_mesa_is_alpha_to_coverage_enabled(const struct gl_context *ctx) 1046b8e80941Smrg{ 1047b8e80941Smrg bool buffer0_is_integer = ctx->DrawBuffer->_IntegerBuffers & 0x1; 1048b8e80941Smrg return (ctx->Multisample.SampleAlphaToCoverage && 1049b8e80941Smrg _mesa_is_multisample_enabled(ctx) && 1050b8e80941Smrg !buffer0_is_integer); 1051b8e80941Smrg} 1052