Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /**************************************************************************
  2.  *
  3.  * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
  4.  * All Rights Reserved.
  5.  *
  6.  * Permission is hereby granted, free of charge, to any person obtaining a
  7.  * copy of this software and associated documentation files (the
  8.  * "Software"), to deal in the Software without restriction, including
  9.  * without limitation the rights to use, copy, modify, merge, publish,
  10.  * distribute, sub license, and/or sell copies of the Software, and to
  11.  * permit persons to whom the Software is furnished to do so, subject to
  12.  * the following conditions:
  13.  *
  14.  * The above copyright notice and this permission notice (including the
  15.  * next paragraph) shall be included in all copies or substantial portions
  16.  * of the Software.
  17.  *
  18.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  19.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  20.  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
  21.  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
  22.  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  23.  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  24.  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  25.  *
  26.  **************************************************************************/
  27.  
  28.  
  29. /**
  30.  * Framebuffer/renderbuffer functions.
  31.  *
  32.  * \author Brian Paul
  33.  */
  34.  
  35.  
  36. #include "main/imports.h"
  37. #include "main/context.h"
  38. #include "main/fbobject.h"
  39. #include "main/framebuffer.h"
  40. #include "main/macros.h"
  41. #include "main/renderbuffer.h"
  42.  
  43. #include "pipe/p_context.h"
  44. #include "pipe/p_defines.h"
  45. #include "pipe/p_screen.h"
  46. #include "st_context.h"
  47. #include "st_cb_fbo.h"
  48. #include "st_cb_flush.h"
  49. #include "st_format.h"
  50. #include "st_texture.h"
  51. #include "st_manager.h"
  52.  
  53. #include "util/u_format.h"
  54. #include "util/u_inlines.h"
  55. #include "util/u_surface.h"
  56.  
  57.  
  58. /**
  59.  * gl_renderbuffer::AllocStorage()
  60.  * This is called to allocate the original drawing surface, and
  61.  * during window resize.
  62.  */
  63. static GLboolean
  64. st_renderbuffer_alloc_storage(struct gl_context * ctx, struct gl_renderbuffer *rb,
  65.                               GLenum internalFormat,
  66.                               GLuint width, GLuint height)
  67. {
  68.    struct st_context *st = st_context(ctx);
  69.    struct pipe_context *pipe = st->pipe;
  70.    struct pipe_screen *screen = st->pipe->screen;
  71.    struct st_renderbuffer *strb = st_renderbuffer(rb);
  72.    enum pipe_format format;
  73.    struct pipe_surface surf_tmpl;
  74.  
  75.    if (strb->format != PIPE_FORMAT_NONE)
  76.       format = strb->format;
  77.    else
  78.       format = st_choose_renderbuffer_format(screen, internalFormat, rb->NumSamples);
  79.      
  80.    /* init renderbuffer fields */
  81.    strb->Base.Width  = width;
  82.    strb->Base.Height = height;
  83.    strb->Base.Format = st_pipe_format_to_mesa_format(format);
  84.    strb->Base._BaseFormat = _mesa_base_fbo_format(ctx, internalFormat);
  85.    strb->Base.DataType = st_format_datatype(format);
  86.  
  87.    strb->defined = GL_FALSE;  /* undefined contents now */
  88.  
  89.    if (strb->software) {
  90.       size_t size;
  91.      
  92.       free(strb->data);
  93.  
  94.       assert(strb->format != PIPE_FORMAT_NONE);
  95.      
  96.       strb->stride = util_format_get_stride(strb->format, width);
  97.       size = util_format_get_2d_size(strb->format, strb->stride, height);
  98.      
  99.       strb->data = malloc(size);
  100.      
  101.       return strb->data != NULL;
  102.    }
  103.    else {
  104.       struct pipe_resource template;
  105.    
  106.       /* Free the old surface and texture
  107.        */
  108.       pipe_surface_reference( &strb->surface, NULL );
  109.       pipe_resource_reference( &strb->texture, NULL );
  110.       pipe_sampler_view_reference(&strb->sampler_view, NULL);
  111.  
  112.       /* Setup new texture template.
  113.        */
  114.       memset(&template, 0, sizeof(template));
  115.       template.target = st->internal_target;
  116.       template.format = format;
  117.       template.width0 = width;
  118.       template.height0 = height;
  119.       template.depth0 = 1;
  120.       template.array_size = 1;
  121.       template.last_level = 0;
  122.       template.nr_samples = rb->NumSamples;
  123.       if (util_format_is_depth_or_stencil(format)) {
  124.          template.bind = PIPE_BIND_DEPTH_STENCIL;
  125.       }
  126.       else {
  127.          template.bind = (PIPE_BIND_DISPLAY_TARGET |
  128.                           PIPE_BIND_RENDER_TARGET);
  129.       }
  130.  
  131.       strb->texture = screen->resource_create(screen, &template);
  132.  
  133.       if (!strb->texture)
  134.          return FALSE;
  135.  
  136.       memset(&surf_tmpl, 0, sizeof(surf_tmpl));
  137.       u_surface_default_template(&surf_tmpl, strb->texture, template.bind);
  138.       strb->surface = pipe->create_surface(pipe,
  139.                                            strb->texture,
  140.                                            &surf_tmpl);
  141.       if (strb->surface) {
  142.          assert(strb->surface->texture);
  143.          assert(strb->surface->format);
  144.          assert(strb->surface->width == width);
  145.          assert(strb->surface->height == height);
  146.       }
  147.  
  148.       return strb->surface != NULL;
  149.    }
  150. }
  151.  
  152.  
  153. /**
  154.  * gl_renderbuffer::Delete()
  155.  */
  156. static void
  157. st_renderbuffer_delete(struct gl_renderbuffer *rb)
  158. {
  159.    struct st_renderbuffer *strb = st_renderbuffer(rb);
  160.    ASSERT(strb);
  161.    pipe_surface_reference(&strb->surface, NULL);
  162.    pipe_resource_reference(&strb->texture, NULL);
  163.    pipe_sampler_view_reference(&strb->sampler_view, NULL);
  164.    free(strb->data);
  165.    free(strb);
  166. }
  167.  
  168.  
  169. /**
  170.  * gl_renderbuffer::GetPointer()
  171.  */
  172. static void *
  173. null_get_pointer(struct gl_context * ctx, struct gl_renderbuffer *rb,
  174.                  GLint x, GLint y)
  175. {
  176.    /* By returning NULL we force all software rendering to go through
  177.     * the span routines.
  178.     */
  179. #if 0
  180.    assert(0);  /* Should never get called with softpipe */
  181. #endif
  182.    return NULL;
  183. }
  184.  
  185.  
  186. /**
  187.  * Called via ctx->Driver.NewFramebuffer()
  188.  */
  189. static struct gl_framebuffer *
  190. st_new_framebuffer(struct gl_context *ctx, GLuint name)
  191. {
  192.    /* XXX not sure we need to subclass gl_framebuffer for pipe */
  193.    return _mesa_new_framebuffer(ctx, name);
  194. }
  195.  
  196.  
  197. /**
  198.  * Called via ctx->Driver.NewRenderbuffer()
  199.  */
  200. static struct gl_renderbuffer *
  201. st_new_renderbuffer(struct gl_context *ctx, GLuint name)
  202. {
  203.    struct st_renderbuffer *strb = ST_CALLOC_STRUCT(st_renderbuffer);
  204.    if (strb) {
  205.       _mesa_init_renderbuffer(&strb->Base, name);
  206.       strb->Base.Delete = st_renderbuffer_delete;
  207.       strb->Base.AllocStorage = st_renderbuffer_alloc_storage;
  208.       strb->Base.GetPointer = null_get_pointer;
  209.       strb->format = PIPE_FORMAT_NONE;
  210.       return &strb->Base;
  211.    }
  212.    return NULL;
  213. }
  214.  
  215.  
  216. /**
  217.  * Allocate a renderbuffer for a an on-screen window (not a user-created
  218.  * renderbuffer).  The window system code determines the format.
  219.  */
  220. struct gl_renderbuffer *
  221. st_new_renderbuffer_fb(enum pipe_format format, int samples, boolean sw)
  222. {
  223.    struct st_renderbuffer *strb;
  224.  
  225.    strb = ST_CALLOC_STRUCT(st_renderbuffer);
  226.    if (!strb) {
  227.       _mesa_error(NULL, GL_OUT_OF_MEMORY, "creating renderbuffer");
  228.       return NULL;
  229.    }
  230.  
  231.    _mesa_init_renderbuffer(&strb->Base, 0);
  232.    strb->Base.ClassID = 0x4242; /* just a unique value */
  233.    strb->Base.NumSamples = samples;
  234.    strb->Base.Format = st_pipe_format_to_mesa_format(format);
  235.    strb->Base._BaseFormat = _mesa_get_format_base_format(strb->Base.Format);
  236.    strb->Base.DataType = st_format_datatype(format);
  237.    strb->format = format;
  238.    strb->software = sw;
  239.    
  240.    switch (format) {
  241.    case PIPE_FORMAT_R8G8B8A8_UNORM:
  242.    case PIPE_FORMAT_B8G8R8A8_UNORM:
  243.    case PIPE_FORMAT_A8R8G8B8_UNORM:
  244.    case PIPE_FORMAT_R8G8B8X8_UNORM:
  245.    case PIPE_FORMAT_B8G8R8X8_UNORM:
  246.    case PIPE_FORMAT_X8R8G8B8_UNORM:
  247.    case PIPE_FORMAT_B5G5R5A1_UNORM:
  248.    case PIPE_FORMAT_B4G4R4A4_UNORM:
  249.    case PIPE_FORMAT_B5G6R5_UNORM:
  250.       strb->Base.InternalFormat = GL_RGBA;
  251.       break;
  252.    case PIPE_FORMAT_Z16_UNORM:
  253.       strb->Base.InternalFormat = GL_DEPTH_COMPONENT16;
  254.       break;
  255.    case PIPE_FORMAT_Z32_UNORM:
  256.       strb->Base.InternalFormat = GL_DEPTH_COMPONENT32;
  257.       break;
  258.    case PIPE_FORMAT_Z24_UNORM_S8_USCALED:
  259.    case PIPE_FORMAT_S8_USCALED_Z24_UNORM:
  260.    case PIPE_FORMAT_Z24X8_UNORM:
  261.    case PIPE_FORMAT_X8Z24_UNORM:
  262.       strb->Base.InternalFormat = GL_DEPTH24_STENCIL8_EXT;
  263.       break;
  264.    case PIPE_FORMAT_S8_USCALED:
  265.       strb->Base.InternalFormat = GL_STENCIL_INDEX8_EXT;
  266.       break;
  267.    case PIPE_FORMAT_R16G16B16A16_SNORM:
  268.       strb->Base.InternalFormat = GL_RGBA16;
  269.       break;
  270.    case PIPE_FORMAT_R8_UNORM:
  271.       strb->Base.InternalFormat = GL_R8;
  272.       break;
  273.    case PIPE_FORMAT_R8G8_UNORM:
  274.       strb->Base.InternalFormat = GL_RG8;
  275.       break;
  276.    case PIPE_FORMAT_R16_UNORM:
  277.       strb->Base.InternalFormat = GL_R16;
  278.       break;
  279.    case PIPE_FORMAT_R16G16_UNORM:
  280.       strb->Base.InternalFormat = GL_RG16;
  281.       break;
  282.    default:
  283.       _mesa_problem(NULL,
  284.                     "Unexpected format in st_new_renderbuffer_fb");
  285.       free(strb);
  286.       return NULL;
  287.    }
  288.  
  289.    /* st-specific methods */
  290.    strb->Base.Delete = st_renderbuffer_delete;
  291.    strb->Base.AllocStorage = st_renderbuffer_alloc_storage;
  292.    strb->Base.GetPointer = null_get_pointer;
  293.  
  294.    /* surface is allocated in st_renderbuffer_alloc_storage() */
  295.    strb->surface = NULL;
  296.  
  297.    return &strb->Base;
  298. }
  299.  
  300.  
  301.  
  302.  
  303. /**
  304.  * Called via ctx->Driver.BindFramebufferEXT().
  305.  */
  306. static void
  307. st_bind_framebuffer(struct gl_context *ctx, GLenum target,
  308.                     struct gl_framebuffer *fb, struct gl_framebuffer *fbread)
  309. {
  310.  
  311. }
  312.  
  313. /**
  314.  * Called by ctx->Driver.FramebufferRenderbuffer
  315.  */
  316. static void
  317. st_framebuffer_renderbuffer(struct gl_context *ctx,
  318.                             struct gl_framebuffer *fb,
  319.                             GLenum attachment,
  320.                             struct gl_renderbuffer *rb)
  321. {
  322.    /* XXX no need for derivation? */
  323.    _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb);
  324. }
  325.  
  326.  
  327. /**
  328.  * Called by ctx->Driver.RenderTexture
  329.  */
  330. static void
  331. st_render_texture(struct gl_context *ctx,
  332.                   struct gl_framebuffer *fb,
  333.                   struct gl_renderbuffer_attachment *att)
  334. {
  335.    struct st_context *st = st_context(ctx);
  336.    struct pipe_context *pipe = st->pipe;
  337.    struct st_renderbuffer *strb;
  338.    struct gl_renderbuffer *rb;
  339.    struct pipe_resource *pt = st_get_texobj_resource(att->Texture);
  340.    struct st_texture_object *stObj;
  341.    const struct gl_texture_image *texImage;
  342.    struct pipe_surface surf_tmpl;
  343.  
  344.    /* When would this fail?  Perhaps assert? */
  345.    if (!pt)
  346.       return;
  347.  
  348.    /* get pointer to texture image we're rendeing to */
  349.    texImage = att->Texture->Image[att->CubeMapFace][att->TextureLevel];
  350.  
  351.    /* create new renderbuffer which wraps the texture image */
  352.    rb = st_new_renderbuffer(ctx, 0);
  353.    if (!rb) {
  354.       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glFramebufferTexture()");
  355.       return;
  356.    }
  357.  
  358.    _mesa_reference_renderbuffer(&att->Renderbuffer, rb);
  359.    assert(rb->RefCount == 1);
  360.    rb->AllocStorage = NULL; /* should not get called */
  361.    strb = st_renderbuffer(rb);
  362.  
  363.    assert(strb->Base.RefCount > 0);
  364.  
  365.    /* get the texture for the texture object */
  366.    stObj = st_texture_object(att->Texture);
  367.  
  368.    /* point renderbuffer at texobject */
  369.    strb->rtt = stObj;
  370.    strb->rtt_level = att->TextureLevel;
  371.    strb->rtt_face = att->CubeMapFace;
  372.    strb->rtt_slice = att->Zoffset;
  373.  
  374.    rb->Width = texImage->Width2;
  375.    rb->Height = texImage->Height2;
  376.    rb->_BaseFormat = texImage->_BaseFormat;
  377.    /*printf("***** render to texture level %d: %d x %d\n", att->TextureLevel, rb->Width, rb->Height);*/
  378.  
  379.    /*printf("***** pipe texture %d x %d\n", pt->width0, pt->height0);*/
  380.  
  381.    pipe_resource_reference( &strb->texture, pt );
  382.  
  383.    pipe_surface_reference(&strb->surface, NULL);
  384.  
  385.    pipe_sampler_view_reference(&strb->sampler_view,
  386.                                st_get_texture_sampler_view(stObj, pipe));
  387.  
  388.    assert(strb->rtt_level <= strb->texture->last_level);
  389.  
  390.    /* new surface for rendering into the texture */
  391.    memset(&surf_tmpl, 0, sizeof(surf_tmpl));
  392.    surf_tmpl.format = strb->texture->format;
  393.    surf_tmpl.usage = PIPE_BIND_RENDER_TARGET;
  394.    surf_tmpl.u.tex.level = strb->rtt_level;
  395.    surf_tmpl.u.tex.first_layer = strb->rtt_face + strb->rtt_slice;
  396.    surf_tmpl.u.tex.last_layer = strb->rtt_face + strb->rtt_slice;
  397.    strb->surface = pipe->create_surface(pipe,
  398.                                         strb->texture,
  399.                                         &surf_tmpl);
  400.  
  401.    strb->format = pt->format;
  402.  
  403.    strb->Base.Format = st_pipe_format_to_mesa_format(pt->format);
  404.    strb->Base.DataType = st_format_datatype(pt->format);
  405.  
  406.    /*
  407.    printf("RENDER TO TEXTURE obj=%p pt=%p surf=%p  %d x %d\n",
  408.           att->Texture, pt, strb->surface, rb->Width, rb->Height);
  409.    */
  410.  
  411.    /* Invalidate buffer state so that the pipe's framebuffer state
  412.     * gets updated.
  413.     * That's where the new renderbuffer (which we just created) gets
  414.     * passed to the pipe as a (color/depth) render target.
  415.     */
  416.    st_invalidate_state(ctx, _NEW_BUFFERS);
  417. }
  418.  
  419.  
  420. /**
  421.  * Called via ctx->Driver.FinishRenderTexture.
  422.  */
  423. static void
  424. st_finish_render_texture(struct gl_context *ctx,
  425.                          struct gl_renderbuffer_attachment *att)
  426. {
  427.    struct st_context *st = st_context(ctx);
  428.    struct st_renderbuffer *strb = st_renderbuffer(att->Renderbuffer);
  429.  
  430.    if (!strb)
  431.       return;
  432.  
  433.    st_flush(st, PIPE_FLUSH_RENDER_CACHE, NULL);
  434.  
  435.    strb->rtt = NULL;
  436.  
  437.    /*
  438.    printf("FINISH RENDER TO TEXTURE surf=%p\n", strb->surface);
  439.    */
  440.  
  441.    /* restore previous framebuffer state */
  442.    st_invalidate_state(ctx, _NEW_BUFFERS);
  443. }
  444.  
  445.  
  446. /**
  447.  * Validate a renderbuffer attachment for a particular set of bindings.
  448.  */
  449. static GLboolean
  450. st_validate_attachment(struct pipe_screen *screen,
  451.                        const struct gl_renderbuffer_attachment *att,
  452.                        unsigned bindings)
  453. {
  454.    const struct st_texture_object *stObj = st_texture_object(att->Texture);
  455.  
  456.    /* Only validate texture attachments for now, since
  457.     * st_renderbuffer_alloc_storage makes sure that
  458.     * the format is supported.
  459.     */
  460.    if (att->Type != GL_TEXTURE)
  461.       return GL_TRUE;
  462.  
  463.    if (!stObj)
  464.       return GL_FALSE;
  465.  
  466.    return screen->is_format_supported(screen, stObj->pt->format,
  467.                                       PIPE_TEXTURE_2D,
  468.                                       stObj->pt->nr_samples, bindings, 0);
  469. }
  470.  
  471.  
  472. /**
  473.  * Check if two renderbuffer attachments name a combined depth/stencil
  474.  * renderbuffer.
  475.  */
  476. GLboolean
  477. st_is_depth_stencil_combined(const struct gl_renderbuffer_attachment *depth,
  478.                              const struct gl_renderbuffer_attachment *stencil)
  479. {
  480.    assert(depth && stencil);
  481.  
  482.    if (depth->Type == stencil->Type) {
  483.       if (depth->Type == GL_RENDERBUFFER_EXT &&
  484.           depth->Renderbuffer == stencil->Renderbuffer)
  485.          return GL_TRUE;
  486.  
  487.       if (depth->Type == GL_TEXTURE &&
  488.           depth->Texture == stencil->Texture)
  489.          return GL_TRUE;
  490.    }
  491.  
  492.    return GL_FALSE;
  493. }
  494.  
  495.  
  496. /**
  497.  * Check that the framebuffer configuration is valid in terms of what
  498.  * the driver can support.
  499.  *
  500.  * For Gallium we only supports combined Z+stencil, not separate buffers.
  501.  */
  502. static void
  503. st_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)
  504. {
  505.    struct st_context *st = st_context(ctx);
  506.    struct pipe_screen *screen = st->pipe->screen;
  507.    const struct gl_renderbuffer_attachment *depth =
  508.          &fb->Attachment[BUFFER_DEPTH];
  509.    const struct gl_renderbuffer_attachment *stencil =
  510.          &fb->Attachment[BUFFER_STENCIL];
  511.    GLuint i;
  512.  
  513.    if (depth->Type && stencil->Type && depth->Type != stencil->Type) {
  514.       fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
  515.       return;
  516.    }
  517.    if (depth->Type == GL_RENDERBUFFER_EXT &&
  518.        stencil->Type == GL_RENDERBUFFER_EXT &&
  519.        depth->Renderbuffer != stencil->Renderbuffer) {
  520.       fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
  521.       return;
  522.    }
  523.    if (depth->Type == GL_TEXTURE &&
  524.        stencil->Type == GL_TEXTURE &&
  525.        depth->Texture != stencil->Texture) {
  526.       fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
  527.       return;
  528.    }
  529.  
  530.    if (!st_validate_attachment(screen,
  531.                                depth,
  532.                                PIPE_BIND_DEPTH_STENCIL)) {
  533.       fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
  534.       return;
  535.    }
  536.    if (!st_validate_attachment(screen,
  537.                                stencil,
  538.                                PIPE_BIND_DEPTH_STENCIL)) {
  539.       fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
  540.       return;
  541.    }
  542.    for (i = 0; i < ctx->Const.MaxColorAttachments; i++) {
  543.       if (!st_validate_attachment(screen,
  544.                                   &fb->Attachment[BUFFER_COLOR0 + i],
  545.                                   PIPE_BIND_RENDER_TARGET)) {
  546.          fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
  547.          return;
  548.       }
  549.    }
  550. }
  551.  
  552.  
  553. /**
  554.  * Called via glDrawBuffer.
  555.  */
  556. static void
  557. st_DrawBuffers(struct gl_context *ctx, GLsizei count, const GLenum *buffers)
  558. {
  559.    struct st_context *st = st_context(ctx);
  560.    struct gl_framebuffer *fb = ctx->DrawBuffer;
  561.    GLuint i;
  562.  
  563.    (void) count;
  564.    (void) buffers;
  565.  
  566.    /* add the renderbuffers on demand */
  567.    for (i = 0; i < fb->_NumColorDrawBuffers; i++) {
  568.       gl_buffer_index idx = fb->_ColorDrawBufferIndexes[i];
  569.       st_manager_add_color_renderbuffer(st, fb, idx);
  570.    }
  571. }
  572.  
  573.  
  574. /**
  575.  * Called via glReadBuffer.
  576.  */
  577. static void
  578. st_ReadBuffer(struct gl_context *ctx, GLenum buffer)
  579. {
  580.    struct st_context *st = st_context(ctx);
  581.    struct gl_framebuffer *fb = ctx->ReadBuffer;
  582.  
  583.    (void) buffer;
  584.  
  585.    /* add the renderbuffer on demand */
  586.    st_manager_add_color_renderbuffer(st, fb, fb->_ColorReadBufferIndex);
  587. }
  588.  
  589.  
  590. void st_init_fbo_functions(struct dd_function_table *functions)
  591. {
  592. #if FEATURE_EXT_framebuffer_object
  593.    functions->NewFramebuffer = st_new_framebuffer;
  594.    functions->NewRenderbuffer = st_new_renderbuffer;
  595.    functions->BindFramebuffer = st_bind_framebuffer;
  596.    functions->FramebufferRenderbuffer = st_framebuffer_renderbuffer;
  597.    functions->RenderTexture = st_render_texture;
  598.    functions->FinishRenderTexture = st_finish_render_texture;
  599.    functions->ValidateFramebuffer = st_validate_framebuffer;
  600. #endif
  601.    /* no longer needed by core Mesa, drivers handle resizes...
  602.    functions->ResizeBuffers = st_resize_buffers;
  603.    */
  604.  
  605.    functions->DrawBuffers = st_DrawBuffers;
  606.    functions->ReadBuffer = st_ReadBuffer;
  607. }
  608.  
  609. /* XXX unused ? */
  610. struct pipe_sampler_view *
  611. st_get_renderbuffer_sampler_view(struct st_renderbuffer *rb,
  612.                                  struct pipe_context *pipe)
  613. {
  614.    if (!rb->sampler_view) {
  615.       rb->sampler_view = st_create_texture_sampler_view(pipe, rb->texture);
  616.    }
  617.  
  618.    return rb->sampler_view;
  619. }
  620.