📄 framebuffer.c
字号:
/*
* Mesa 3-D graphics library
* Version: 6.4
*
* Copyright (C) 1999-2005 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 "context.h"
#include "mtypes.h"
#include "fbobject.h"
#include "framebuffer.h"
#include "renderbuffer.h"
/**
* Compute/set the _DepthMax field for the given framebuffer.
* This value depends on the Z buffer resolution.
*/
static void
compute_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;
fb->_MRD = 1.0; /* Minimum resolvable depth value, for polygon offset */
}
/**
* 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;
assert(name != 0);
fb = CALLOC_STRUCT(gl_framebuffer);
if (fb) {
fb->Name = name;
fb->RefCount = 1;
fb->Delete = _mesa_destroy_framebuffer;
fb->ColorDrawBuffer[0] = GL_COLOR_ATTACHMENT0_EXT;
fb->_ColorDrawBufferMask[0] = BUFFER_BIT_COLOR0;
fb->ColorReadBuffer = GL_COLOR_ATTACHMENT0_EXT;
fb->_ColorReadBufferMask = BUFFER_BIT_COLOR0;
fb->Delete = _mesa_destroy_framebuffer;
}
return fb;
}
/**
* Initialize a gl_framebuffer object.
* \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));
/* save the visual */
fb->Visual = *visual;
/* Init glRead/DrawBuffer state */
if (visual->doubleBufferMode) {
fb->ColorDrawBuffer[0] = GL_BACK;
fb->_ColorDrawBufferMask[0] = BUFFER_BIT_BACK_LEFT;
fb->ColorReadBuffer = GL_BACK;
fb->_ColorReadBufferMask = BUFFER_BIT_BACK_LEFT;
}
else {
fb->ColorDrawBuffer[0] = GL_FRONT;
fb->_ColorDrawBufferMask[0] = BUFFER_BIT_FRONT_LEFT;
fb->ColorReadBuffer = GL_FRONT;
fb->_ColorReadBufferMask = BUFFER_BIT_FRONT_LEFT;
}
fb->Delete = _mesa_destroy_framebuffer;
fb->_Status = GL_FRAMEBUFFER_COMPLETE_EXT;
compute_depth_max(fb);
}
/**
* Create/attach software-based renderbuffers to the given framebuffer.
* This is a helper routine for device drivers. Drivers can just as well
* call the individual _mesa_add_*_renderbuffer() routines directly.
*/
void
_mesa_add_soft_renderbuffers(struct gl_framebuffer *fb,
GLboolean color,
GLboolean depth,
GLboolean stencil,
GLboolean accum,
GLboolean alpha,
GLboolean aux)
{
GLboolean frontLeft = GL_TRUE;
GLboolean backLeft = fb->Visual.doubleBufferMode;
GLboolean frontRight = fb->Visual.stereoMode;
GLboolean backRight = fb->Visual.stereoMode && fb->Visual.doubleBufferMode;
if (color) {
if (fb->Visual.rgbMode) {
assert(fb->Visual.redBits == fb->Visual.greenBits);
assert(fb->Visual.redBits == fb->Visual.blueBits);
_mesa_add_color_renderbuffers(NULL, fb,
fb->Visual.redBits,
fb->Visual.alphaBits,
frontLeft, backLeft,
frontRight, backRight);
}
else {
_mesa_add_color_index_renderbuffers(NULL, fb,
fb->Visual.indexBits,
frontLeft, backLeft,
frontRight, backRight);
}
}
if (depth) {
assert(fb->Visual.depthBits > 0);
_mesa_add_depth_renderbuffer(NULL, fb, fb->Visual.depthBits);
}
if (stencil) {
assert(fb->Visual.stencilBits > 0);
_mesa_add_stencil_renderbuffer(NULL, fb, fb->Visual.stencilBits);
}
if (accum) {
assert(fb->Visual.rgbMode);
assert(fb->Visual.accumRedBits > 0);
assert(fb->Visual.accumGreenBits > 0);
assert(fb->Visual.accumBlueBits > 0);
_mesa_add_accum_renderbuffer(NULL, fb,
fb->Visual.accumRedBits,
fb->Visual.accumGreenBits,
fb->Visual.accumBlueBits,
fb->Visual.accumAlphaBits);
}
if (aux) {
assert(fb->Visual.rgbMode);
assert(fb->Visual.numAuxBuffers > 0);
_mesa_add_aux_renderbuffers(NULL, fb, fb->Visual.redBits,
fb->Visual.numAuxBuffers);
}
#if 1
if (alpha) {
assert(fb->Visual.rgbMode);
assert(fb->Visual.alphaBits > 0);
_mesa_add_alpha_renderbuffers(NULL, fb, fb->Visual.alphaBits,
frontLeft, backLeft,
frontRight, backRight);
}
#endif
#if 0
if (multisample) {
/* maybe someday */
}
#endif
}
/**
* Deallocate buffer and everything attached to it.
*/
void
_mesa_destroy_framebuffer(struct gl_framebuffer *buffer)
{
if (buffer) {
_mesa_free_framebuffer_data(buffer);
FREE(buffer);
}
}
/**
* 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);
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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -