st_cb_fbo.c

Go to the documentation of this file.
00001 /**************************************************************************
00002  * 
00003  * Copyright 2007 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 
00036 #include "main/imports.h"
00037 #include "main/context.h"
00038 #include "main/fbobject.h"
00039 #include "main/framebuffer.h"
00040 #include "main/renderbuffer.h"
00041 
00042 #include "pipe/p_context.h"
00043 #include "pipe/p_defines.h"
00044 #include "pipe/p_inlines.h"
00045 #include "pipe/p_winsys.h"
00046 #include "st_context.h"
00047 #include "st_cb_fbo.h"
00048 #include "st_cb_texture.h"
00049 #include "st_format.h"
00050 #include "st_public.h"
00051 #include "st_texture.h"
00052 
00053 
00054 
00058 static int
00059 init_renderbuffer_bits(struct st_renderbuffer *strb,
00060                        enum pipe_format pipeFormat)
00061 {
00062    struct pipe_format_info info;
00063 
00064    if (!st_get_format_info( pipeFormat, &info )) {
00065       assert( 0 );
00066    }
00067 
00068    strb->Base._ActualFormat = info.base_format;
00069    strb->Base.RedBits = info.red_bits;
00070    strb->Base.GreenBits = info.green_bits;
00071    strb->Base.BlueBits = info.blue_bits;
00072    strb->Base.AlphaBits = info.alpha_bits;
00073    strb->Base.DepthBits = info.depth_bits;
00074    strb->Base.StencilBits = info.stencil_bits;
00075    strb->Base.DataType = st_format_datatype(pipeFormat);
00076 
00077    return info.size;
00078 }
00079 
00085 static GLboolean
00086 st_renderbuffer_alloc_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
00087                               GLenum internalFormat,
00088                               GLuint width, GLuint height)
00089 {
00090    struct pipe_context *pipe = ctx->st->pipe;
00091    struct st_renderbuffer *strb = st_renderbuffer(rb);
00092    struct pipe_texture template;
00093    unsigned surface_usage;
00094 
00095    /* Free the old surface and texture
00096     */
00097    pipe_surface_reference( &strb->surface, NULL );
00098    pipe_texture_reference( &strb->texture, NULL );
00099 
00100 
00101    memset(&template, 0, sizeof(template));
00102 
00103    if (strb->format != PIPE_FORMAT_NONE) {
00104       template.format = strb->format;
00105    }
00106    else {
00107       template.format = st_choose_renderbuffer_format(pipe, internalFormat);
00108    }
00109 
00110    strb->Base.Width  = width;
00111    strb->Base.Height = height;
00112    init_renderbuffer_bits(strb, template.format);
00113 
00114    template.target = PIPE_TEXTURE_2D;
00115    template.compressed = 0;
00116    pf_get_block(template.format, &template.block);
00117    template.width[0] = width;
00118    template.height[0] = height;
00119    template.depth[0] = 1;
00120    template.last_level = 0;
00121    template.nr_samples = rb->Samples;
00122 
00123    if (pf_is_depth_stencil(template.format)) {
00124       template.tex_usage = PIPE_TEXTURE_USAGE_DEPTH_STENCIL;
00125    }
00126    else {
00127       template.tex_usage = (PIPE_TEXTURE_USAGE_DISPLAY_TARGET |
00128                             PIPE_TEXTURE_USAGE_RENDER_TARGET);
00129    }
00130 
00131 
00132    /* Probably need dedicated flags for surface usage too: 
00133     */
00134    surface_usage = (PIPE_BUFFER_USAGE_GPU_READ |
00135                     PIPE_BUFFER_USAGE_GPU_WRITE);
00136 #if 0
00137                     PIPE_BUFFER_USAGE_CPU_READ |
00138                     PIPE_BUFFER_USAGE_CPU_WRITE);
00139 #endif
00140 
00141    strb->texture = pipe->screen->texture_create( pipe->screen,
00142                                                  &template );
00143 
00144    /* Special path for accum buffers.  
00145     *
00146     * Try a different surface format.  Since accum buffers are s/w
00147     * only for now, the surface pixel format doesn't really matter,
00148     * only that the buffer is large enough.
00149     */
00150    if (!strb->texture && template.format == DEFAULT_ACCUM_PIPE_FORMAT) 
00151    {
00152       /* Actually, just setting this usage value should be sufficient
00153        * to tell the driver to go ahead and allocate the buffer, even
00154        * if HW doesn't support the format.
00155        */
00156       template.tex_usage = 0;
00157       surface_usage = (PIPE_BUFFER_USAGE_CPU_READ |
00158                        PIPE_BUFFER_USAGE_CPU_WRITE);
00159 
00160       strb->texture = pipe->screen->texture_create( pipe->screen,
00161                                                     &template );
00162 
00163    }
00164 
00165    if (!strb->texture) 
00166       return FALSE;
00167 
00168    strb->surface = pipe->screen->get_tex_surface( pipe->screen,
00169                                                   strb->texture,
00170                                                   0, 0, 0,
00171                                                   surface_usage );
00172 
00173    assert(strb->surface->texture);
00174    assert(strb->surface->buffer);
00175    assert(strb->surface->format);
00176    assert(strb->surface->block.size);
00177    assert(strb->surface->block.width);
00178    assert(strb->surface->block.height);
00179    assert(strb->surface->width == width);
00180    assert(strb->surface->height == height);
00181    assert(strb->surface->stride);
00182 
00183 
00184    return strb->surface != NULL;
00185 }
00186 
00187 
00191 static void
00192 st_renderbuffer_delete(struct gl_renderbuffer *rb)
00193 {
00194    struct st_renderbuffer *strb = st_renderbuffer(rb);
00195    ASSERT(strb);
00196    pipe_surface_reference(&strb->surface, NULL);
00197    pipe_texture_reference(&strb->texture, NULL);
00198    free(strb);
00199 }
00200 
00201 
00205 static void *
00206 null_get_pointer(GLcontext * ctx, struct gl_renderbuffer *rb,
00207                  GLint x, GLint y)
00208 {
00209    /* By returning NULL we force all software rendering to go through
00210     * the span routines.
00211     */
00212 #if 0
00213    assert(0);  /* Should never get called with softpipe */
00214 #endif
00215    return NULL;
00216 }
00217 
00218 
00222 static struct gl_framebuffer *
00223 st_new_framebuffer(GLcontext *ctx, GLuint name)
00224 {
00225    /* XXX not sure we need to subclass gl_framebuffer for pipe */
00226    return _mesa_new_framebuffer(ctx, name);
00227 }
00228 
00229 
00233 static struct gl_renderbuffer *
00234 st_new_renderbuffer(GLcontext *ctx, GLuint name)
00235 {
00236    struct st_renderbuffer *strb = CALLOC_STRUCT(st_renderbuffer);
00237    if (strb) {
00238       _mesa_init_renderbuffer(&strb->Base, name);
00239       strb->Base.Delete = st_renderbuffer_delete;
00240       strb->Base.AllocStorage = st_renderbuffer_alloc_storage;
00241       strb->Base.GetPointer = null_get_pointer;
00242       strb->format = PIPE_FORMAT_NONE;
00243       return &strb->Base;
00244    }
00245    return NULL;
00246 }
00247 
00248 
00253 struct gl_renderbuffer *
00254 st_new_renderbuffer_fb(enum pipe_format format, int samples)
00255 {
00256    struct st_renderbuffer *strb;
00257 
00258    strb = CALLOC_STRUCT(st_renderbuffer);
00259    if (!strb) {
00260       _mesa_error(NULL, GL_OUT_OF_MEMORY, "creating renderbuffer");
00261       return NULL;
00262    }
00263 
00264    _mesa_init_renderbuffer(&strb->Base, 0);
00265    strb->Base.ClassID = 0x4242; /* just a unique value */
00266    strb->Base.Samples = samples;
00267    strb->format = format;
00268 
00269    switch (format) {
00270    case PIPE_FORMAT_A8R8G8B8_UNORM:
00271    case PIPE_FORMAT_B8G8R8A8_UNORM:
00272    case PIPE_FORMAT_X8R8G8B8_UNORM:
00273    case PIPE_FORMAT_B8G8R8X8_UNORM:
00274    case PIPE_FORMAT_A1R5G5B5_UNORM:
00275    case PIPE_FORMAT_A4R4G4B4_UNORM:
00276    case PIPE_FORMAT_R5G6B5_UNORM:
00277       strb->Base.InternalFormat = GL_RGBA;
00278       strb->Base._BaseFormat = GL_RGBA;
00279       break;
00280    case PIPE_FORMAT_Z16_UNORM:
00281       strb->Base.InternalFormat = GL_DEPTH_COMPONENT16;
00282       strb->Base._BaseFormat = GL_DEPTH_COMPONENT;
00283       break;
00284    case PIPE_FORMAT_Z32_UNORM:
00285       strb->Base.InternalFormat = GL_DEPTH_COMPONENT32;
00286       strb->Base._BaseFormat = GL_DEPTH_COMPONENT;
00287       break;
00288    case PIPE_FORMAT_S8Z24_UNORM:
00289    case PIPE_FORMAT_Z24S8_UNORM:
00290    case PIPE_FORMAT_X8Z24_UNORM:
00291    case PIPE_FORMAT_Z24X8_UNORM:
00292       strb->Base.InternalFormat = GL_DEPTH24_STENCIL8_EXT;
00293       strb->Base._BaseFormat = GL_DEPTH_STENCIL_EXT;
00294       break;
00295    case PIPE_FORMAT_S8_UNORM:
00296       strb->Base.InternalFormat = GL_STENCIL_INDEX8_EXT;
00297       strb->Base._BaseFormat = GL_STENCIL_INDEX;
00298       break;
00299    case DEFAULT_ACCUM_PIPE_FORMAT: /*PIPE_FORMAT_R16G16B16A16_SNORM*/
00300       strb->Base.InternalFormat = GL_RGBA16;
00301       strb->Base._BaseFormat = GL_RGBA;
00302       break;
00303    default:
00304       _mesa_problem(NULL,
00305                     "Unexpected format in st_new_renderbuffer_fb");
00306       return NULL;
00307    }
00308 
00309    /* st-specific methods */
00310    strb->Base.Delete = st_renderbuffer_delete;
00311    strb->Base.AllocStorage = st_renderbuffer_alloc_storage;
00312    strb->Base.GetPointer = null_get_pointer;
00313 
00314    /* surface is allocated in st_renderbuffer_alloc_storage() */
00315    strb->surface = NULL;
00316 
00317    return &strb->Base;
00318 }
00319 
00320 
00321 
00322 
00326 static void
00327 st_bind_framebuffer(GLcontext *ctx, GLenum target,
00328                     struct gl_framebuffer *fb, struct gl_framebuffer *fbread)
00329 {
00330 
00331 }
00332 
00336 static void
00337 st_framebuffer_renderbuffer(GLcontext *ctx, 
00338                             struct gl_framebuffer *fb,
00339                             GLenum attachment,
00340                             struct gl_renderbuffer *rb)
00341 {
00342    /* XXX no need for derivation? */
00343    _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb);
00344 }
00345 
00346 
00350 static void
00351 st_render_texture(GLcontext *ctx,
00352                   struct gl_framebuffer *fb,
00353                   struct gl_renderbuffer_attachment *att)
00354 {
00355    struct st_renderbuffer *strb;
00356    struct gl_renderbuffer *rb;
00357    struct pipe_texture *pt;
00358    struct st_texture_object *stObj;
00359    const struct gl_texture_image *texImage =
00360       att->Texture->Image[att->CubeMapFace][att->TextureLevel];
00361 
00362 
00363    assert(!att->Renderbuffer);
00364 
00365    /* create new renderbuffer which wraps the texture image */
00366    rb = st_new_renderbuffer(ctx, 0);
00367    if (!rb) {
00368       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glFramebufferTexture()");
00369       return;
00370    }
00371 
00372    _mesa_reference_renderbuffer(&att->Renderbuffer, rb);
00373    assert(rb->RefCount == 1);
00374    rb->AllocStorage = NULL; /* should not get called */
00375    strb = st_renderbuffer(rb);
00376 
00377    /* get the texture for the texture object */
00378    stObj = st_texture_object(att->Texture);
00379 
00380    /* point renderbuffer at texobject */
00381    strb->rtt = stObj;
00382    strb->rtt_level = att->TextureLevel;
00383    strb->rtt_face = att->CubeMapFace;
00384    strb->rtt_slice = att->Zoffset;
00385 
00386    rb->Width = texImage->Width2;
00387    rb->Height = texImage->Height2;
00388    /*printf("***** render to texture level %d: %d x %d\n", att->TextureLevel, rb->Width, rb->Height);*/
00389 
00390    pt = st_get_texobj_texture(att->Texture);
00391    assert(pt);
00392    /*printf("***** pipe texture %d x %d\n", pt->width[0], pt->height[0]);*/
00393 
00394    pipe_texture_reference( &strb->texture, pt );
00395 
00396    pipe_surface_reference(&strb->surface, NULL);
00397 
00398    /* the new surface will be created during framebuffer validation */
00399 
00400    init_renderbuffer_bits(strb, pt->format);
00401 
00402    /*
00403    printf("RENDER TO TEXTURE obj=%p pt=%p surf=%p  %d x %d\n",
00404           att->Texture, pt, strb->surface, rb->Width, rb->Height);
00405    */
00406 
00407    /* Invalidate buffer state so that the pipe's framebuffer state
00408     * gets updated.
00409     * That's where the new renderbuffer (which we just created) gets
00410     * passed to the pipe as a (color/depth) render target.
00411     */
00412    st_invalidate_state(ctx, _NEW_BUFFERS);
00413 }
00414 
00415 
00419 static void
00420 st_finish_render_texture(GLcontext *ctx,
00421                          struct gl_renderbuffer_attachment *att)
00422 {
00423    struct pipe_screen *screen = ctx->st->pipe->screen;
00424    struct st_renderbuffer *strb = st_renderbuffer(att->Renderbuffer);
00425 
00426    if (!strb)
00427       return;
00428 
00429    st_flush( ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL );
00430 
00431    if (strb->surface)
00432       screen->tex_surface_release( screen, &strb->surface );
00433 
00434    strb->rtt = NULL;
00435 
00436    /*
00437    printf("FINISH RENDER TO TEXTURE surf=%p\n", strb->surface);
00438    */
00439 
00440    _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
00441 
00442    /* restore previous framebuffer state */
00443    st_invalidate_state(ctx, _NEW_BUFFERS);
00444 }
00445 
00446 
00447 
00448 void st_init_fbo_functions(struct dd_function_table *functions)
00449 {
00450    functions->NewFramebuffer = st_new_framebuffer;
00451    functions->NewRenderbuffer = st_new_renderbuffer;
00452    functions->BindFramebuffer = st_bind_framebuffer;
00453    functions->FramebufferRenderbuffer = st_framebuffer_renderbuffer;
00454    functions->RenderTexture = st_render_texture;
00455    functions->FinishRenderTexture = st_finish_render_texture;
00456    /* no longer needed by core Mesa, drivers handle resizes...
00457    functions->ResizeBuffers = st_resize_buffers;
00458    */
00459 }

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