st_framebuffer.c

Go to the documentation of this file.
00001 /**************************************************************************
00002  * 
00003  * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
00004  * All Rights Reserved.
00005  * 
00006  * Permission is hereby granted, free of charge, to any person obtaining a
00007  * copy of this software and associated documentation files (the
00008  * "Software"), to deal in the Software without restriction, including
00009  * without limitation the rights to use, copy, modify, merge, publish,
00010  * distribute, sub license, and/or sell copies of the Software, and to
00011  * permit persons to whom the Software is furnished to do so, subject to
00012  * the following conditions:
00013  * 
00014  * The above copyright notice and this permission notice (including the
00015  * next paragraph) shall be included in all copies or substantial portions
00016  * of the Software.
00017  * 
00018  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00019  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00020  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
00021  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
00022  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
00023  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
00024  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00025  * 
00026  **************************************************************************/
00027 
00028 
00029 #include "main/imports.h"
00030 #include "main/buffers.h"
00031 #include "main/context.h"
00032 #include "main/framebuffer.h"
00033 #include "main/matrix.h"
00034 #include "main/renderbuffer.h"
00035 #include "main/scissor.h"
00036 #include "st_public.h"
00037 #include "st_context.h"
00038 #include "st_cb_fbo.h"
00039 #include "pipe/p_defines.h"
00040 #include "pipe/p_context.h"
00041 #include "pipe/p_inlines.h"
00042 
00043 
00044 struct st_framebuffer *
00045 st_create_framebuffer( const __GLcontextModes *visual,
00046                        enum pipe_format colorFormat,
00047                        enum pipe_format depthFormat,
00048                        enum pipe_format stencilFormat,
00049                        uint width, uint height,
00050                        void *private)
00051 {
00052    struct st_framebuffer *stfb = CALLOC_STRUCT(st_framebuffer);
00053    if (stfb) {
00054       int samples = st_get_msaa();
00055 
00056       if (visual->sampleBuffers)
00057          samples = visual->samples;
00058 
00059       _mesa_initialize_framebuffer(&stfb->Base, visual);
00060 
00061       {
00062          /* fake frontbuffer */
00063          /* XXX allocation should only happen in the unusual case
00064             it's actually needed */
00065          struct gl_renderbuffer *rb
00066             = st_new_renderbuffer_fb(colorFormat, samples);
00067          _mesa_add_renderbuffer(&stfb->Base, BUFFER_FRONT_LEFT, rb);
00068       }
00069 
00070       if (visual->doubleBufferMode) {
00071          struct gl_renderbuffer *rb
00072             = st_new_renderbuffer_fb(colorFormat, samples);
00073          _mesa_add_renderbuffer(&stfb->Base, BUFFER_BACK_LEFT, rb);
00074       }
00075 
00076       if (depthFormat == stencilFormat && depthFormat != PIPE_FORMAT_NONE) {
00077          /* combined depth/stencil buffer */
00078          struct gl_renderbuffer *depthStencilRb
00079             = st_new_renderbuffer_fb(depthFormat, samples);
00080          /* note: bind RB to two attachment points */
00081          _mesa_add_renderbuffer(&stfb->Base, BUFFER_DEPTH, depthStencilRb);
00082          _mesa_add_renderbuffer(&stfb->Base, BUFFER_STENCIL, depthStencilRb);
00083       }
00084       else {
00085          /* separate depth and/or stencil */
00086 
00087          if (visual->depthBits == 32) {
00088             /* 32-bit depth buffer */
00089             struct gl_renderbuffer *depthRb
00090                = st_new_renderbuffer_fb(depthFormat, samples);
00091             _mesa_add_renderbuffer(&stfb->Base, BUFFER_DEPTH, depthRb);
00092          }
00093          else if (visual->depthBits == 24) {
00094             /* 24-bit depth buffer, ignore stencil bits */
00095             struct gl_renderbuffer *depthRb
00096                = st_new_renderbuffer_fb(depthFormat, samples);
00097             _mesa_add_renderbuffer(&stfb->Base, BUFFER_DEPTH, depthRb);
00098          }
00099          else if (visual->depthBits > 0) {
00100             /* 16-bit depth buffer */
00101             struct gl_renderbuffer *depthRb
00102                = st_new_renderbuffer_fb(depthFormat, samples);
00103             _mesa_add_renderbuffer(&stfb->Base, BUFFER_DEPTH, depthRb);
00104          }
00105 
00106          if (visual->stencilBits > 0) {
00107             /* 8-bit stencil */
00108             struct gl_renderbuffer *stencilRb
00109                = st_new_renderbuffer_fb(stencilFormat, samples);
00110             _mesa_add_renderbuffer(&stfb->Base, BUFFER_STENCIL, stencilRb);
00111          }
00112       }
00113 
00114       if (visual->accumRedBits > 0) {
00115          /* 16-bit/channel accum */
00116          struct gl_renderbuffer *accumRb
00117             = st_new_renderbuffer_fb(DEFAULT_ACCUM_PIPE_FORMAT, 0); /* XXX accum isn't multisampled right? */
00118          _mesa_add_renderbuffer(&stfb->Base, BUFFER_ACCUM, accumRb);
00119       }
00120 
00121       stfb->Base.Initialized = GL_TRUE;
00122       stfb->InitWidth = width;
00123       stfb->InitHeight = height;
00124       stfb->Private = private;
00125    }
00126    return stfb;
00127 }
00128 
00129 
00130 void st_resize_framebuffer( struct st_framebuffer *stfb,
00131                             uint width, uint height )
00132 {
00133    if (stfb->Base.Width != width || stfb->Base.Height != height) {
00134       GET_CURRENT_CONTEXT(ctx);
00135       if (ctx) {
00136          if (stfb->InitWidth == 0 && stfb->InitHeight == 0) {
00137             /* didn't have a valid size until now */
00138             stfb->InitWidth = width;
00139             stfb->InitHeight = height;
00140             if (ctx->Viewport.Width <= 1) {
00141                /* set context's initial viewport/scissor size */
00142                _mesa_set_viewport(ctx, 0, 0, width, height);
00143                _mesa_set_scissor(ctx, 0, 0, width, height);
00144             }
00145          }
00146 
00147          _mesa_resize_framebuffer(ctx, &stfb->Base, width, height);
00148 
00149          assert(stfb->Base.Width == width);
00150          assert(stfb->Base.Height == height);
00151       }
00152    }
00153 }
00154 
00155 
00156 void st_unreference_framebuffer( struct st_framebuffer **stfb )
00157 {
00158    _mesa_unreference_framebuffer((struct gl_framebuffer **) stfb);
00159 }
00160 
00161 
00162 
00168 void
00169 st_set_framebuffer_surface(struct st_framebuffer *stfb,
00170                            uint surfIndex, struct pipe_surface *surf)
00171 {
00172    static const GLuint invalid_size = 9999999;
00173    struct st_renderbuffer *strb;
00174    GLuint width, height, i;
00175 
00176    assert(surfIndex < BUFFER_COUNT);
00177 
00178    strb = st_renderbuffer(stfb->Base.Attachment[surfIndex].Renderbuffer);
00179    assert(strb);
00180 
00181    /* replace the renderbuffer's surface/texture pointers */
00182    pipe_surface_reference( &strb->surface, surf );
00183    pipe_texture_reference( &strb->texture, surf->texture );
00184 
00185    /* update renderbuffer's width/height */
00186    strb->Base.Width = surf->width;
00187    strb->Base.Height = surf->height;
00188 
00189    /* Try to update the framebuffer's width/height from the renderbuffer
00190     * sizes.  Before we start drawing, all the rbs _should_ be the same size.
00191     */
00192    width = height = invalid_size;
00193    for (i = 0; i < BUFFER_COUNT; i++) {
00194       if (stfb->Base.Attachment[i].Renderbuffer) {
00195          if (width == invalid_size) {
00196             width = stfb->Base.Attachment[i].Renderbuffer->Width;
00197             height = stfb->Base.Attachment[i].Renderbuffer->Height;
00198          }
00199          else if (width != stfb->Base.Attachment[i].Renderbuffer->Width ||
00200                   height != stfb->Base.Attachment[i].Renderbuffer->Height) {
00201             /* inconsistant renderbuffer sizes, bail out */
00202             return;
00203          }
00204       }
00205    }
00206 
00207    if (width != invalid_size) {
00208       /* OK, the renderbuffers are of a consistant size, so update the
00209        * parent framebuffer's size.
00210        */
00211       stfb->Base.Width = width;
00212       stfb->Base.Height = height;
00213    }
00214 }
00215 
00216 
00217 
00221 struct pipe_surface *
00222 st_get_framebuffer_surface(struct st_framebuffer *stfb, uint surfIndex)
00223 {
00224    struct st_renderbuffer *strb;
00225 
00226    assert(surfIndex <= ST_SURFACE_DEPTH);
00227 
00228    /* sanity checks, ST tokens should match Mesa tokens */
00229    assert(ST_SURFACE_FRONT_LEFT == BUFFER_FRONT_LEFT);
00230    assert(ST_SURFACE_BACK_RIGHT == BUFFER_BACK_RIGHT);
00231 
00232    strb = st_renderbuffer(stfb->Base.Attachment[surfIndex].Renderbuffer);
00233    if (strb)
00234       return strb->surface;
00235    return NULL;
00236 }
00237 
00238 struct pipe_texture *
00239 st_get_framebuffer_texture(struct st_framebuffer *stfb, uint surfIndex)
00240 {
00241    struct st_renderbuffer *strb;
00242 
00243    assert(surfIndex <= ST_SURFACE_DEPTH);
00244 
00245    /* sanity checks, ST tokens should match Mesa tokens */
00246    assert(ST_SURFACE_FRONT_LEFT == BUFFER_FRONT_LEFT);
00247    assert(ST_SURFACE_BACK_RIGHT == BUFFER_BACK_RIGHT);
00248 
00249    strb = st_renderbuffer(stfb->Base.Attachment[surfIndex].Renderbuffer);
00250    if (strb)
00251       return strb->texture;
00252    return NULL;
00253 }
00254 
00260 void
00261 st_notify_swapbuffers(struct st_framebuffer *stfb)
00262 {
00263    GET_CURRENT_CONTEXT(ctx);
00264 
00265    if (ctx && ctx->DrawBuffer == &stfb->Base) {
00266       st_flush( ctx->st, 
00267                 PIPE_FLUSH_RENDER_CACHE | 
00268                 PIPE_FLUSH_SWAPBUFFERS |
00269                 PIPE_FLUSH_FRAME,
00270                 NULL );
00271       ctx->st->frontbuffer_status = FRONT_STATUS_COPY_OF_BACK;
00272    }
00273 }
00274 
00275 
00280 void
00281 st_notify_swapbuffers_complete(struct st_framebuffer *stfb)
00282 {
00283    GET_CURRENT_CONTEXT(ctx);
00284 
00285    if (ctx && ctx->DrawBuffer == &stfb->Base) {
00286       struct st_renderbuffer *strb;
00287 
00288       /* Mark back color buffers as undefined */
00289       strb = st_renderbuffer(stfb->Base.Attachment[BUFFER_BACK_LEFT].
00290                              Renderbuffer);
00291       if (strb && strb->surface)
00292          strb->surface->status = PIPE_SURFACE_STATUS_UNDEFINED;
00293 
00294       strb = st_renderbuffer(stfb->Base.Attachment[BUFFER_BACK_RIGHT].
00295                              Renderbuffer);
00296       if (strb && strb->surface)
00297          strb->surface->status = PIPE_SURFACE_STATUS_UNDEFINED;
00298    }
00299 }
00300 
00301 
00302 void *st_framebuffer_private( struct st_framebuffer *stfb )
00303 {
00304    return stfb->Private;
00305 }
00306 

Generated on Tue Sep 29 06:25:18 2009 for Gallium3D by  doxygen 1.5.4