00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
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    
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    
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    
00145 
00146 
00147 
00148 
00149 
00150    if (!strb->texture && template.format == DEFAULT_ACCUM_PIPE_FORMAT) 
00151    {
00152       
00153 
00154 
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    
00210 
00211 
00212 #if 0
00213    assert(0);  
00214 #endif
00215    return NULL;
00216 }
00217 
00218 
00222 static struct gl_framebuffer *
00223 st_new_framebuffer(GLcontext *ctx, GLuint name)
00224 {
00225    
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; 
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: 
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    
00310    strb->Base.Delete = st_renderbuffer_delete;
00311    strb->Base.AllocStorage = st_renderbuffer_alloc_storage;
00312    strb->Base.GetPointer = null_get_pointer;
00313 
00314    
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    
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    
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; 
00375    strb = st_renderbuffer(rb);
00376 
00377    
00378    stObj = st_texture_object(att->Texture);
00379 
00380    
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    
00389 
00390    pt = st_get_texobj_texture(att->Texture);
00391    assert(pt);
00392    
00393 
00394    pipe_texture_reference( &strb->texture, pt );
00395 
00396    pipe_surface_reference(&strb->surface, NULL);
00397 
00398    
00399 
00400    init_renderbuffer_bits(strb, pt->format);
00401 
00402    
00403 
00404 
00405 
00406 
00407    
00408 
00409 
00410 
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 
00438 
00439 
00440    _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
00441 
00442    
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    
00457 
00458 
00459 }