⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 framebuffer.c

📁 Mesa is an open-source implementation of the OpenGL specification - a system for rendering interacti
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Mesa 3-D graphics library * Version:  7.2 * * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *//** * Functions for allocating/managing framebuffers and renderbuffers. * Also, routines for reading/writing renderbuffer data as ubytes, * ushorts, uints, etc. */#include "glheader.h"#include "imports.h"#include "buffers.h"#include "context.h"#include "depthstencil.h"#include "mtypes.h"#include "fbobject.h"#include "framebuffer.h"#include "renderbuffer.h"#include "texobj.h"/** * Compute/set the _DepthMax field for the given framebuffer. * This value depends on the Z buffer resolution. */static voidcompute_depth_max(struct gl_framebuffer *fb){   if (fb->Visual.depthBits == 0) {      /* Special case.  Even if we don't have a depth buffer we need       * good values for DepthMax for Z vertex transformation purposes       * and for per-fragment fog computation.       */      fb->_DepthMax = (1 << 16) - 1;   }   else if (fb->Visual.depthBits < 32) {      fb->_DepthMax = (1 << fb->Visual.depthBits) - 1;   }   else {      /* Special case since shift values greater than or equal to the       * number of bits in the left hand expression's type are undefined.       */      fb->_DepthMax = 0xffffffff;   }   fb->_DepthMaxF = (GLfloat) fb->_DepthMax;   /* Minimum resolvable depth value, for polygon offset */   fb->_MRD = 1.0 / fb->_DepthMaxF;}/** * Create and initialize a gl_framebuffer object. * This is intended for creating _window_system_ framebuffers, not generic * framebuffer objects ala GL_EXT_framebuffer_object. * * \sa _mesa_new_framebuffer */struct gl_framebuffer *_mesa_create_framebuffer(const GLvisual *visual){   struct gl_framebuffer *fb = CALLOC_STRUCT(gl_framebuffer);   assert(visual);   if (fb) {      _mesa_initialize_framebuffer(fb, visual);   }   return fb;}/** * Allocate a new gl_framebuffer object. * This is the default function for ctx->Driver.NewFramebuffer(). * This is for allocating user-created framebuffers, not window-system * framebuffers! * \sa _mesa_create_framebuffer */struct gl_framebuffer *_mesa_new_framebuffer(GLcontext *ctx, GLuint name){   struct gl_framebuffer *fb;   (void) ctx;   assert(name != 0);   fb = CALLOC_STRUCT(gl_framebuffer);   if (fb) {      fb->Name = name;      fb->RefCount = 1;      fb->_NumColorDrawBuffers = 1;      fb->ColorDrawBuffer[0] = GL_COLOR_ATTACHMENT0_EXT;      fb->_ColorDrawBufferIndexes[0] = BUFFER_COLOR0;      fb->ColorReadBuffer = GL_COLOR_ATTACHMENT0_EXT;      fb->_ColorReadBufferIndex = BUFFER_COLOR0;      fb->Delete = _mesa_destroy_framebuffer;   }   return fb;}/** * Initialize a gl_framebuffer object.  Typically used to initialize * window system-created framebuffers, not user-created framebuffers. * \sa _mesa_create_framebuffer */void_mesa_initialize_framebuffer(struct gl_framebuffer *fb, const GLvisual *visual){   assert(fb);   assert(visual);   _mesa_bzero(fb, sizeof(struct gl_framebuffer));   _glthread_INIT_MUTEX(fb->Mutex);   fb->RefCount = 1;   /* save the visual */   fb->Visual = *visual;   /* Init read/draw renderbuffer state */   if (visual->doubleBufferMode) {      fb->_NumColorDrawBuffers = 1;      fb->ColorDrawBuffer[0] = GL_BACK;      fb->_ColorDrawBufferIndexes[0] = BUFFER_BACK_LEFT;      fb->ColorReadBuffer = GL_BACK;      fb->_ColorReadBufferIndex = BUFFER_BACK_LEFT;   }   else {      fb->_NumColorDrawBuffers = 1;      fb->ColorDrawBuffer[0] = GL_FRONT;      fb->_ColorDrawBufferIndexes[0] = BUFFER_FRONT_LEFT;      fb->ColorReadBuffer = GL_FRONT;      fb->_ColorReadBufferIndex = BUFFER_FRONT_LEFT;   }   fb->Delete = _mesa_destroy_framebuffer;   fb->_Status = GL_FRAMEBUFFER_COMPLETE_EXT;   compute_depth_max(fb);}/** * Deallocate buffer and everything attached to it. * Typically called via the gl_framebuffer->Delete() method. */void_mesa_destroy_framebuffer(struct gl_framebuffer *fb){   if (fb) {      _mesa_free_framebuffer_data(fb);      _mesa_free(fb);   }}/** * Free all the data hanging off the given gl_framebuffer, but don't free * the gl_framebuffer object itself. */void_mesa_free_framebuffer_data(struct gl_framebuffer *fb){   GLuint i;   assert(fb);   assert(fb->RefCount == 0);   _glthread_DESTROY_MUTEX(fb->Mutex);   for (i = 0; i < BUFFER_COUNT; i++) {      struct gl_renderbuffer_attachment *att = &fb->Attachment[i];      if (att->Renderbuffer) {         _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);      }      if (att->Texture) {         _mesa_reference_texobj(&att->Texture, NULL);      }      ASSERT(!att->Renderbuffer);      ASSERT(!att->Texture);      att->Type = GL_NONE;   }   /* unbind _Depth/_StencilBuffer to decr ref counts */   _mesa_reference_renderbuffer(&fb->_DepthBuffer, NULL);   _mesa_reference_renderbuffer(&fb->_StencilBuffer, NULL);}/** * Set *ptr to point to fb, with refcounting and locking. */void_mesa_reference_framebuffer(struct gl_framebuffer **ptr,                            struct gl_framebuffer *fb){   assert(ptr);   if (*ptr == fb) {      /* no change */      return;   }   if (*ptr) {      _mesa_unreference_framebuffer(ptr);   }   assert(!*ptr);   assert(fb);   _glthread_LOCK_MUTEX(fb->Mutex);   fb->RefCount++;   _glthread_UNLOCK_MUTEX(fb->Mutex);   *ptr = fb;}/** * Undo/remove a reference to a framebuffer object. * Decrement the framebuffer object's reference count and delete it when * the refcount hits zero. * Note: we pass the address of a pointer and set it to NULL. */void_mesa_unreference_framebuffer(struct gl_framebuffer **fb){   assert(fb);   if (*fb) {      GLboolean deleteFlag = GL_FALSE;      _glthread_LOCK_MUTEX((*fb)->Mutex);      ASSERT((*fb)->RefCount > 0);      (*fb)->RefCount--;      deleteFlag = ((*fb)->RefCount == 0);      _glthread_UNLOCK_MUTEX((*fb)->Mutex);            if (deleteFlag)         (*fb)->Delete(*fb);      *fb = NULL;   }}/** * Resize the given framebuffer's renderbuffers to the new width and height. * This should only be used for window-system framebuffers, not * user-created renderbuffers (i.e. made with GL_EXT_framebuffer_object). * This will typically be called via ctx->Driver.ResizeBuffers() or directly * from a device driver. * * \note it's possible for ctx to be null since a window can be resized * without a currently bound rendering context. */void_mesa_resize_framebuffer(GLcontext *ctx, struct gl_framebuffer *fb,                         GLuint width, GLuint height){   GLuint i;   /* XXX I think we could check if the size is not changing    * and return early.    */   /* For window system framebuffers, Name is zero */   assert(fb->Name == 0);   for (i = 0; i < BUFFER_COUNT; i++) {      struct gl_renderbuffer_attachment *att = &fb->Attachment[i];      if (att->Type == GL_RENDERBUFFER_EXT && att->Renderbuffer) {         struct gl_renderbuffer *rb = att->Renderbuffer;         /* only resize if size is changing */         if (rb->Width != width || rb->Height != height) {            /* could just as well pass rb->_ActualFormat here */            if (rb->AllocStorage(ctx, rb, rb->InternalFormat, width, height)) {               ASSERT(rb->Width == width);               ASSERT(rb->Height == height);            }            else {               _mesa_error(ctx, GL_OUT_OF_MEMORY, "Resizing framebuffer");               /* no return */            }         }      }   }   if (fb->_DepthBuffer) {      struct gl_renderbuffer *rb = fb->_DepthBuffer;      if (rb->Width != width || rb->Height != height) {         if (!rb->AllocStorage(ctx, rb, rb->InternalFormat, width, height)) {            _mesa_error(ctx, GL_OUT_OF_MEMORY, "Resizing framebuffer");         }      }   }   if (fb->_StencilBuffer) {      struct gl_renderbuffer *rb = fb->_StencilBuffer;      if (rb->Width != width || rb->Height != height) {         if (!rb->AllocStorage(ctx, rb, rb->InternalFormat, width, height)) {            _mesa_error(ctx, GL_OUT_OF_MEMORY, "Resizing framebuffer");         }      }   }   fb->Width = width;   fb->Height = height;   if (ctx) {      /* update scissor / window bounds */      _mesa_update_draw_buffer_bounds(ctx);      /* Signal new buffer state so that swrast will update its clipping       * info (the CLIP_BIT flag).       */      ctx->NewState |= _NEW_BUFFERS;   }}/** * Examine all the framebuffer's renderbuffers to update the Width/Height * fields of the framebuffer.  If we have renderbuffers with different * sizes, set the framebuffer's width and height to zero. * Note: this is only intended for user-created framebuffers, not * window-system framebuffes. */static voidupdate_framebuffer_size(struct gl_framebuffer *fb){   GLboolean haveSize = GL_FALSE;   GLuint i;   /* user-created framebuffers only */   assert(fb->Name);   for (i = 0; i < BUFFER_COUNT; i++) {      struct gl_renderbuffer_attachment *att = &fb->Attachment[i];      const struct gl_renderbuffer *rb = att->Renderbuffer;      if (rb) {         if (haveSize) {            if (rb->Width != fb->Width && rb->Height != fb->Height) {               /* size mismatch! */               fb->Width = 0;               fb->Height = 0;               return;            }         }         else {            fb->Width = rb->Width;            fb->Height = rb->Height;            haveSize = GL_TRUE;         }      }   }}/** * Update the context's current drawing buffer's Xmin, Xmax, Ymin, Ymax fields. * These values are computed from the buffer's width and height and * the scissor box, if it's enabled. * \param ctx  the GL context. */void_mesa_update_draw_buffer_bounds(GLcontext *ctx){   struct gl_framebuffer *buffer = ctx->DrawBuffer;   if (!buffer)      return;   if (buffer->Name) {      /* user-created framebuffer size depends on the renderbuffers */      update_framebuffer_size(buffer);   }   buffer->_Xmin = 0;   buffer->_Ymin = 0;   buffer->_Xmax = buffer->Width;   buffer->_Ymax = buffer->Height;   if (ctx->Scissor.Enabled) {      if (ctx->Scissor.X > buffer->_Xmin) {	 buffer->_Xmin = ctx->Scissor.X;      }      if (ctx->Scissor.Y > buffer->_Ymin) {	 buffer->_Ymin = ctx->Scissor.Y;      }      if (ctx->Scissor.X + ctx->Scissor.Width < buffer->_Xmax) {	 buffer->_Xmax = ctx->Scissor.X + ctx->Scissor.Width;      }      if (ctx->Scissor.Y + ctx->Scissor.Height < buffer->_Ymax) {	 buffer->_Ymax = ctx->Scissor.Y + ctx->Scissor.Height;      }      /* finally, check for empty region */      if (buffer->_Xmin > buffer->_Xmax) {         buffer->_Xmin = buffer->_Xmax;      }      if (buffer->_Ymin > buffer->_Ymax) {         buffer->_Ymin = buffer->_Ymax;      }   }   ASSERT(buffer->_Xmin <= buffer->_Xmax);   ASSERT(buffer->_Ymin <= buffer->_Ymax);}/** * The glGet queries of the framebuffer red/green/blue size, stencil size, * etc. are satisfied by the fields of ctx->DrawBuffer->Visual.  These can * change depending on the renderbuffer bindings.  This function updates * the given framebuffer's Visual from the current renderbuffer bindings. * * This may apply to user-created framebuffers or window system framebuffers. * * Also note: ctx->DrawBuffer->Visual.depthBits might not equal * ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer.DepthBits. * The former one is used to convert floating point depth values into * integer Z values. */void_mesa_update_framebuffer_visual(struct gl_framebuffer *fb){   GLuint i;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -