Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /**************************************************************************
  2.  *
  3.  * Copyright 2008 Red Hat Inc.
  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. #include "main/imports.h"
  30. #include "main/macros.h"
  31. #include "main/mtypes.h"
  32. #include "main/enums.h"
  33. #include "main/fbobject.h"
  34. #include "main/framebuffer.h"
  35. #include "main/renderbuffer.h"
  36. #include "main/context.h"
  37. #include "swrast/swrast.h"
  38. #include "drivers/common/meta.h"
  39.  
  40. #include "radeon_common.h"
  41. #include "radeon_mipmap_tree.h"
  42.  
  43. #define FILE_DEBUG_FLAG RADEON_TEXTURE
  44. #define DBG(...) do {                                           \
  45.         if (RADEON_DEBUG & FILE_DEBUG_FLAG)                      \
  46.                 printf(__VA_ARGS__);                      \
  47. } while(0)
  48.  
  49. static struct gl_framebuffer *
  50. radeon_new_framebuffer(struct gl_context *ctx, GLuint name)
  51. {
  52.   return _mesa_new_framebuffer(ctx, name);
  53. }
  54.  
  55. static void
  56. radeon_delete_renderbuffer(struct gl_context *ctx, struct gl_renderbuffer *rb)
  57. {
  58.   struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb);
  59.  
  60.   radeon_print(RADEON_TEXTURE, RADEON_TRACE,
  61.                 "%s(rb %p, rrb %p) \n",
  62.                 __func__, rb, rrb);
  63.  
  64.   ASSERT(rrb);
  65.  
  66.   if (rrb && rrb->bo) {
  67.     radeon_bo_unref(rrb->bo);
  68.   }
  69.   _mesa_delete_renderbuffer(ctx, rb);
  70. }
  71.  
  72. #if defined(RADEON_R100)
  73. static GLuint get_depth_z32(const struct radeon_renderbuffer * rrb,
  74.                                GLint x, GLint y)
  75. {
  76.     GLuint ba, address = 0;
  77.  
  78.     ba = (y >> 4) * (rrb->pitch >> 6) + (x >> 4);
  79.  
  80.     address |= (x & 0x7) << 2;
  81.     address |= (y & 0x3) << 5;
  82.     address |= (((x & 0x10) >> 2) ^ (y & 0x4)) << 5;
  83.     address |= (ba & 3) << 8;
  84.     address |= (y & 0x8) << 7;
  85.     address |= (((x & 0x8) << 1) ^ (y & 0x10)) << 7;
  86.     address |= (ba & ~0x3) << 10;
  87.     return address;
  88. }
  89.  
  90. static GLuint get_depth_z16(const struct radeon_renderbuffer * rrb,
  91.                                GLint x, GLint y)
  92. {
  93.     GLuint ba, address = 0;                   /* a[0]    = 0           */
  94.  
  95.     ba = (y / 16) * (rrb->pitch >> 6) + (x / 32);
  96.  
  97.     address |= (x & 0x7) << 1;                /* a[1..3] = x[0..2]     */
  98.     address |= (y & 0x7) << 4;                /* a[4..6] = y[0..2]     */
  99.     address |= (x & 0x8) << 4;                /* a[7]    = x[3]        */
  100.     address |= (ba & 0x3) << 8;               /* a[8..9] = ba[0..1]    */
  101.     address |= (y & 0x8) << 7;                /* a[10]   = y[3]        */
  102.     address |= ((x & 0x10) ^ (y & 0x10)) << 7;/* a[11]   = x[4] ^ y[4] */
  103.     address |= (ba & ~0x3) << 10;             /* a[12..] = ba[2..] */
  104.     return address;
  105. }
  106. #endif
  107.  
  108. #if defined(RADEON_R200)
  109. static GLuint get_depth_z32(const struct radeon_renderbuffer * rrb,
  110.                                  GLint x, GLint y)
  111. {
  112.     GLuint offset;
  113.     GLuint b;
  114.     offset = 0;
  115.     b = (((y & 0x7ff) >> 4) * (rrb->pitch >> 7) + (x >> 5));
  116.     offset += (b >> 1) << 12;
  117.     offset += (((rrb->pitch >> 7) & 0x1) ? (b & 0x1) : ((b & 0x1) ^ ((y >> 4) & 0x1))) << 11;
  118.     offset += ((y >> 2) & 0x3) << 9;
  119.     offset += ((x >> 2) & 0x1) << 8;
  120.     offset += ((x >> 3) & 0x3) << 6;
  121.     offset += ((y >> 1) & 0x1) << 5;
  122.     offset += ((x >> 1) & 0x1) << 4;
  123.     offset += (y & 0x1) << 3;
  124.     offset += (x & 0x1) << 2;
  125.  
  126.     return offset;
  127. }
  128.  
  129. static GLuint get_depth_z16(const struct radeon_renderbuffer *rrb,
  130.                                GLint x, GLint y)
  131. {
  132.    GLuint offset;
  133.    GLuint b;
  134.  
  135.    offset = 0;
  136.    b = (((y  >> 4) * (rrb->pitch >> 7) + (x >> 6)));
  137.    offset += (b >> 1) << 12;
  138.    offset += (((rrb->pitch >> 7) & 0x1) ? (b & 0x1) : ((b & 0x1) ^ ((y >> 4) & 0x1))) << 11;
  139.    offset += ((y >> 2) & 0x3) << 9;
  140.    offset += ((x >> 3) & 0x1) << 8;
  141.    offset += ((x >> 4) & 0x3) << 6;
  142.    offset += ((x >> 2) & 0x1) << 5;
  143.    offset += ((y >> 1) & 0x1) << 4;
  144.    offset += ((x >> 1) & 0x1) << 3;
  145.    offset += (y & 0x1) << 2;
  146.    offset += (x & 0x1) << 1;
  147.  
  148.    return offset;
  149. }
  150. #endif
  151.  
  152. static void
  153. radeon_map_renderbuffer_s8z24(struct gl_context *ctx,
  154.                        struct gl_renderbuffer *rb,
  155.                        GLuint x, GLuint y, GLuint w, GLuint h,
  156.                        GLbitfield mode,
  157.                        GLubyte **out_map,
  158.                        GLint *out_stride)
  159. {
  160.     struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb);
  161.     uint32_t *untiled_s8z24_map, *tiled_s8z24_map;
  162.     int ret;
  163.     int y_flip = (rb->Name == 0) ? -1 : 1;
  164.     int y_bias = (rb->Name == 0) ? (rb->Height - 1) : 0;
  165.     uint32_t pitch = w * rrb->cpp;
  166.  
  167.     rrb->map_pitch = pitch;
  168.  
  169.     rrb->map_buffer = malloc(w * h * 4);
  170.     ret = radeon_bo_map(rrb->bo, !!(mode & GL_MAP_WRITE_BIT));
  171.     assert(!ret);
  172.     untiled_s8z24_map = rrb->map_buffer;
  173.     tiled_s8z24_map = rrb->bo->ptr;
  174.  
  175.     for (uint32_t pix_y = 0; pix_y < h; ++ pix_y) {
  176.         for (uint32_t pix_x = 0; pix_x < w; ++pix_x) {
  177.             uint32_t flipped_y = y_flip * (int32_t)(y + pix_y) + y_bias;
  178.             uint32_t src_offset = get_depth_z32(rrb, x + pix_x, flipped_y);
  179.             uint32_t dst_offset = pix_y * rrb->map_pitch + pix_x * rrb->cpp;
  180.             untiled_s8z24_map[dst_offset/4] = tiled_s8z24_map[src_offset/4];
  181.         }
  182.     }
  183.  
  184.     radeon_bo_unmap(rrb->bo);
  185.                    
  186.     *out_map = rrb->map_buffer;
  187.     *out_stride = rrb->map_pitch;
  188. }
  189.  
  190. static void
  191. radeon_map_renderbuffer_z16(struct gl_context *ctx,
  192.                             struct gl_renderbuffer *rb,
  193.                             GLuint x, GLuint y, GLuint w, GLuint h,
  194.                             GLbitfield mode,
  195.                             GLubyte **out_map,
  196.                             GLint *out_stride)
  197. {
  198.     struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb);
  199.     uint16_t *untiled_z16_map, *tiled_z16_map;
  200.     int ret;
  201.     int y_flip = (rb->Name == 0) ? -1 : 1;
  202.     int y_bias = (rb->Name == 0) ? (rb->Height - 1) : 0;
  203.     uint32_t pitch = w * rrb->cpp;
  204.  
  205.     rrb->map_pitch = pitch;
  206.  
  207.     rrb->map_buffer = malloc(w * h * 2);
  208.     ret = radeon_bo_map(rrb->bo, !!(mode & GL_MAP_WRITE_BIT));
  209.     assert(!ret);
  210.  
  211.     untiled_z16_map = rrb->map_buffer;
  212.     tiled_z16_map = rrb->bo->ptr;
  213.  
  214.     for (uint32_t pix_y = 0; pix_y < h; ++ pix_y) {
  215.         for (uint32_t pix_x = 0; pix_x < w; ++pix_x) {
  216.             uint32_t flipped_y = y_flip * (int32_t)(y + pix_y) + y_bias;
  217.             uint32_t src_offset = get_depth_z16(rrb, x + pix_x, flipped_y);
  218.             uint32_t dst_offset = pix_y * rrb->map_pitch + pix_x * rrb->cpp;
  219.             untiled_z16_map[dst_offset/2] = tiled_z16_map[src_offset/2];
  220.         }
  221.     }
  222.  
  223.     radeon_bo_unmap(rrb->bo);
  224.  
  225.     *out_map = rrb->map_buffer;
  226.     *out_stride = rrb->map_pitch;
  227. }
  228.  
  229. static void
  230. radeon_map_renderbuffer(struct gl_context *ctx,
  231.                        struct gl_renderbuffer *rb,
  232.                        GLuint x, GLuint y, GLuint w, GLuint h,
  233.                        GLbitfield mode,
  234.                        GLubyte **out_map,
  235.                        GLint *out_stride)
  236. {
  237.    struct radeon_context *const rmesa = RADEON_CONTEXT(ctx);
  238.    struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb);
  239.    GLubyte *map;
  240.    GLboolean ok;
  241.    int stride, flip_stride;
  242.    int ret;
  243.    int src_x, src_y;
  244.  
  245.    if (!rrb || !rrb->bo) {
  246.            *out_map = NULL;
  247.            *out_stride = 0;
  248.            return;
  249.    }
  250.  
  251.    rrb->map_mode = mode;
  252.    rrb->map_x = x;
  253.    rrb->map_y = y;
  254.    rrb->map_w = w;
  255.    rrb->map_h = h;
  256.    rrb->map_pitch = rrb->pitch;
  257.  
  258.    ok = rmesa->vtbl.check_blit(rb->Format, rrb->pitch / rrb->cpp);
  259.    if (ok) {
  260.        if (rb->Name) {
  261.            src_x = x;
  262.            src_y = y;
  263.        } else {
  264.            src_x = x;
  265.            src_y = rrb->base.Base.Height - y - h;
  266.        }
  267.  
  268.        /* Make a temporary buffer and blit the current contents of the renderbuffer
  269.         * out to it.  This gives us linear access to the buffer, instead of having
  270.         * to do detiling in software.
  271.         */
  272.  
  273.        rrb->map_pitch = rrb->pitch;
  274.  
  275.        assert(!rrb->map_bo);
  276.        rrb->map_bo = radeon_bo_open(rmesa->radeonScreen->bom, 0,
  277.                                     rrb->map_pitch * h, 4,
  278.                                     RADEON_GEM_DOMAIN_GTT, 0);
  279.        
  280.        ok = rmesa->vtbl.blit(ctx, rrb->bo, rrb->draw_offset,
  281.                              rb->Format, rrb->pitch / rrb->cpp,
  282.                              rb->Width, rb->Height,
  283.                              src_x, src_y,
  284.                              rrb->map_bo, 0,
  285.                              rb->Format, rrb->map_pitch / rrb->cpp,
  286.                              w, h,
  287.                              0, 0,
  288.                              w, h,
  289.                              GL_FALSE);
  290.        assert(ok);
  291.  
  292.        ret = radeon_bo_map(rrb->map_bo, !!(mode & GL_MAP_WRITE_BIT));
  293.        assert(!ret);
  294.  
  295.        map = rrb->map_bo->ptr;
  296.  
  297.        if (rb->Name) {
  298.            *out_map = map;
  299.            *out_stride = rrb->map_pitch;
  300.        } else {
  301.            *out_map = map + (h - 1) * rrb->map_pitch;
  302.            *out_stride = -rrb->map_pitch;
  303.        }
  304.        return;
  305.    }
  306.  
  307.    /* sw fallback flush stuff */
  308.    if (radeon_bo_is_referenced_by_cs(rrb->bo, rmesa->cmdbuf.cs)) {
  309.       radeon_firevertices(rmesa);
  310.    }
  311.  
  312.    if ((rmesa->radeonScreen->chip_flags & RADEON_CHIPSET_DEPTH_ALWAYS_TILED) && !rrb->has_surface) {
  313.        if (rb->Format == MESA_FORMAT_S8_Z24 || rb->Format == MESA_FORMAT_X8_Z24) {
  314.            radeon_map_renderbuffer_s8z24(ctx, rb, x, y, w, h,
  315.                                          mode, out_map, out_stride);
  316.            return;
  317.        }
  318.        if (rb->Format == MESA_FORMAT_Z16) {
  319.            radeon_map_renderbuffer_z16(ctx, rb, x, y, w, h,
  320.                                        mode, out_map, out_stride);
  321.            return;
  322.        }
  323.    }
  324.  
  325.    ret = radeon_bo_map(rrb->bo, !!(mode & GL_MAP_WRITE_BIT));
  326.    assert(!ret);
  327.  
  328.    map = rrb->bo->ptr;
  329.    stride = rrb->map_pitch;
  330.  
  331.    if (rb->Name == 0) {
  332.       y = rb->Height - 1 - y;
  333.       flip_stride = -stride;
  334.    } else {
  335.       flip_stride = stride;
  336.       map += rrb->draw_offset;
  337.    }
  338.  
  339.    map += x * rrb->cpp;
  340.    map += (int)y * stride;
  341.  
  342.    *out_map = map;
  343.    *out_stride = flip_stride;
  344. }
  345.  
  346. static void
  347. radeon_unmap_renderbuffer_s8z24(struct gl_context *ctx,
  348.                           struct gl_renderbuffer *rb)
  349. {
  350.    struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb);
  351.  
  352.    if (!rrb->map_buffer)
  353.      return;
  354.  
  355.    if (rrb->map_mode & GL_MAP_WRITE_BIT) {
  356.        uint32_t *untiled_s8z24_map = rrb->map_buffer;
  357.        uint32_t *tiled_s8z24_map;
  358.        int y_flip = (rb->Name == 0) ? -1 : 1;
  359.        int y_bias = (rb->Name == 0) ? (rb->Height - 1) : 0;
  360.  
  361.        radeon_bo_map(rrb->bo, 1);
  362.        
  363.        tiled_s8z24_map = rrb->bo->ptr;
  364.  
  365.        for (uint32_t pix_y = 0; pix_y < rrb->map_h; pix_y++) {
  366.            for (uint32_t pix_x = 0; pix_x < rrb->map_w; pix_x++) {
  367.                uint32_t flipped_y = y_flip * (int32_t)(pix_y + rrb->map_y) + y_bias;
  368.                uint32_t dst_offset = get_depth_z32(rrb, rrb->map_x + pix_x, flipped_y);
  369.                uint32_t src_offset = pix_y * rrb->map_pitch + pix_x * rrb->cpp;
  370.                tiled_s8z24_map[dst_offset/4] = untiled_s8z24_map[src_offset/4];
  371.            }
  372.        }
  373.        radeon_bo_unmap(rrb->bo);
  374.    }
  375.    free(rrb->map_buffer);
  376.    rrb->map_buffer = NULL;
  377. }
  378.  
  379. static void
  380. radeon_unmap_renderbuffer_z16(struct gl_context *ctx,
  381.                               struct gl_renderbuffer *rb)
  382. {
  383.    struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb);
  384.  
  385.    if (!rrb->map_buffer)
  386.      return;
  387.  
  388.    if (rrb->map_mode & GL_MAP_WRITE_BIT) {
  389.        uint16_t *untiled_z16_map = rrb->map_buffer;
  390.        uint16_t *tiled_z16_map;
  391.        int y_flip = (rb->Name == 0) ? -1 : 1;
  392.        int y_bias = (rb->Name == 0) ? (rb->Height - 1) : 0;
  393.  
  394.        radeon_bo_map(rrb->bo, 1);
  395.        
  396.        tiled_z16_map = rrb->bo->ptr;
  397.  
  398.        for (uint32_t pix_y = 0; pix_y < rrb->map_h; pix_y++) {
  399.            for (uint32_t pix_x = 0; pix_x < rrb->map_w; pix_x++) {
  400.                uint32_t flipped_y = y_flip * (int32_t)(pix_y + rrb->map_y) + y_bias;
  401.                uint32_t dst_offset = get_depth_z16(rrb, rrb->map_x + pix_x, flipped_y);
  402.                uint32_t src_offset = pix_y * rrb->map_pitch + pix_x * rrb->cpp;
  403.                tiled_z16_map[dst_offset/2] = untiled_z16_map[src_offset/2];
  404.            }
  405.        }
  406.        radeon_bo_unmap(rrb->bo);
  407.    }
  408.    free(rrb->map_buffer);
  409.    rrb->map_buffer = NULL;
  410. }
  411.  
  412.  
  413. static void
  414. radeon_unmap_renderbuffer(struct gl_context *ctx,
  415.                           struct gl_renderbuffer *rb)
  416. {
  417.    struct radeon_context *const rmesa = RADEON_CONTEXT(ctx);
  418.    struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb);
  419.    GLboolean ok;
  420.  
  421.    if ((rmesa->radeonScreen->chip_flags & RADEON_CHIPSET_DEPTH_ALWAYS_TILED) && !rrb->has_surface) {
  422.        if (rb->Format == MESA_FORMAT_S8_Z24 || rb->Format == MESA_FORMAT_X8_Z24) {
  423.            radeon_unmap_renderbuffer_s8z24(ctx, rb);
  424.            return;
  425.        }
  426.        if (rb->Format == MESA_FORMAT_Z16) {
  427.            radeon_unmap_renderbuffer_z16(ctx, rb);
  428.            return;
  429.        }
  430.    }
  431.  
  432.    if (!rrb->map_bo) {
  433.            if (rrb->bo)
  434.                    radeon_bo_unmap(rrb->bo);
  435.            return;
  436.    }
  437.  
  438.    radeon_bo_unmap(rrb->map_bo);
  439.  
  440.    if (rrb->map_mode & GL_MAP_WRITE_BIT) {
  441.       ok = rmesa->vtbl.blit(ctx, rrb->map_bo, 0,
  442.                             rb->Format, rrb->map_pitch / rrb->cpp,
  443.                             rrb->map_w, rrb->map_h,
  444.                             0, 0,
  445.                             rrb->bo, rrb->draw_offset,
  446.                             rb->Format, rrb->pitch / rrb->cpp,
  447.                             rb->Width, rb->Height,
  448.                             rrb->map_x, rrb->map_y,
  449.                             rrb->map_w, rrb->map_h,
  450.                             GL_FALSE);
  451.       assert(ok);
  452.    }
  453.  
  454.    radeon_bo_unref(rrb->map_bo);
  455.    rrb->map_bo = NULL;
  456. }
  457.  
  458.  
  459. /**
  460.  * Called via glRenderbufferStorageEXT() to set the format and allocate
  461.  * storage for a user-created renderbuffer.
  462.  */
  463. static GLboolean
  464. radeon_alloc_renderbuffer_storage(struct gl_context * ctx, struct gl_renderbuffer *rb,
  465.                                  GLenum internalFormat,
  466.                                  GLuint width, GLuint height)
  467. {
  468.   struct radeon_context *radeon = RADEON_CONTEXT(ctx);
  469.   struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb);
  470.   uint32_t size, pitch;
  471.   int cpp;
  472.  
  473.   radeon_print(RADEON_TEXTURE, RADEON_TRACE,
  474.                 "%s(%p, rb %p) \n",
  475.                 __func__, ctx, rb);
  476.  
  477.    ASSERT(rb->Name != 0);
  478.   switch (internalFormat) {
  479.    case GL_R3_G3_B2:
  480.    case GL_RGB4:
  481.    case GL_RGB5:
  482.       rb->Format = _radeon_texformat_rgb565;
  483.       cpp = 2;
  484.       break;
  485.    case GL_RGB:
  486.    case GL_RGB8:
  487.    case GL_RGB10:
  488.    case GL_RGB12:
  489.    case GL_RGB16:
  490.       rb->Format = _radeon_texformat_argb8888;
  491.       cpp = 4;
  492.       break;
  493.    case GL_RGBA:
  494.    case GL_RGBA2:
  495.    case GL_RGBA4:
  496.    case GL_RGB5_A1:
  497.    case GL_RGBA8:
  498.    case GL_RGB10_A2:
  499.    case GL_RGBA12:
  500.    case GL_RGBA16:
  501.       rb->Format = _radeon_texformat_argb8888;
  502.       cpp = 4;
  503.       break;
  504.    case GL_STENCIL_INDEX:
  505.    case GL_STENCIL_INDEX1_EXT:
  506.    case GL_STENCIL_INDEX4_EXT:
  507.    case GL_STENCIL_INDEX8_EXT:
  508.    case GL_STENCIL_INDEX16_EXT:
  509.       /* alloc a depth+stencil buffer */
  510.       rb->Format = MESA_FORMAT_S8_Z24;
  511.       cpp = 4;
  512.       break;
  513.    case GL_DEPTH_COMPONENT16:
  514.       rb->Format = MESA_FORMAT_Z16;
  515.       cpp = 2;
  516.       break;
  517.    case GL_DEPTH_COMPONENT:
  518.    case GL_DEPTH_COMPONENT24:
  519.    case GL_DEPTH_COMPONENT32:
  520.       rb->Format = MESA_FORMAT_X8_Z24;
  521.       cpp = 4;
  522.       break;
  523.    case GL_DEPTH_STENCIL_EXT:
  524.    case GL_DEPTH24_STENCIL8_EXT:
  525.       rb->Format = MESA_FORMAT_S8_Z24;
  526.       cpp = 4;
  527.       break;
  528.    default:
  529.       _mesa_problem(ctx,
  530.                     "Unexpected format in radeon_alloc_renderbuffer_storage");
  531.       return GL_FALSE;
  532.    }
  533.  
  534.   rb->_BaseFormat = _mesa_base_fbo_format(ctx, internalFormat);
  535.  
  536.   if (ctx->Driver.Flush)
  537.           ctx->Driver.Flush(ctx); /* +r6/r7 */
  538.  
  539.   if (rrb->bo)
  540.     radeon_bo_unref(rrb->bo);
  541.  
  542.    pitch = ((cpp * width + 63) & ~63) / cpp;
  543.  
  544.    if (RADEON_DEBUG & RADEON_MEMORY)
  545.       fprintf(stderr,"Allocating %d x %d radeon RBO (pitch %d)\n", width,
  546.               height, pitch);
  547.  
  548.    size = pitch * height * cpp;
  549.    rrb->pitch = pitch * cpp;
  550.    rrb->cpp = cpp;
  551.    rrb->bo = radeon_bo_open(radeon->radeonScreen->bom,
  552.                             0,
  553.                             size,
  554.                             0,
  555.                             RADEON_GEM_DOMAIN_VRAM,
  556.                             0);
  557.    rb->Width = width;
  558.    rb->Height = height;
  559.    return GL_TRUE;
  560. }
  561.  
  562. static void
  563. radeon_image_target_renderbuffer_storage(struct gl_context *ctx,
  564.                                          struct gl_renderbuffer *rb,
  565.                                          void *image_handle)
  566. {
  567.    radeonContextPtr radeon = RADEON_CONTEXT(ctx);
  568.    struct radeon_renderbuffer *rrb;
  569.    __DRIscreen *screen;
  570.    __DRIimage *image;
  571.  
  572.    screen = radeon->radeonScreen->driScreen;
  573.    image = screen->dri2.image->lookupEGLImage(screen, image_handle,
  574.                                               screen->loaderPrivate);
  575.    if (image == NULL)
  576.       return;
  577.  
  578.    rrb = radeon_renderbuffer(rb);
  579.  
  580.    if (ctx->Driver.Flush)
  581.       ctx->Driver.Flush(ctx); /* +r6/r7 */
  582.  
  583.    if (rrb->bo)
  584.       radeon_bo_unref(rrb->bo);
  585.    rrb->bo = image->bo;
  586.    radeon_bo_ref(rrb->bo);
  587.    fprintf(stderr, "image->bo: %p, name: %d, rbs: w %d -> p %d\n", image->bo, image->bo->handle,
  588.            image->width, image->pitch);
  589.  
  590.    rrb->cpp = image->cpp;
  591.    rrb->pitch = image->pitch * image->cpp;
  592.  
  593.    rb->Format = image->format;
  594.    rb->InternalFormat = image->internal_format;
  595.    rb->Width = image->width;
  596.    rb->Height = image->height;
  597.    rb->Format = image->format;
  598.    rb->_BaseFormat = _mesa_base_fbo_format(&radeon->glCtx,
  599.                                            image->internal_format);
  600.    rb->NeedsFinishRenderTexture = GL_TRUE;
  601. }
  602.  
  603. /**
  604.  * Called for each hardware renderbuffer when a _window_ is resized.
  605.  * Just update fields.
  606.  * Not used for user-created renderbuffers!
  607.  */
  608. static GLboolean
  609. radeon_alloc_window_storage(struct gl_context * ctx, struct gl_renderbuffer *rb,
  610.                            GLenum internalFormat, GLuint width, GLuint height)
  611. {
  612.    ASSERT(rb->Name == 0);
  613.    rb->Width = width;
  614.    rb->Height = height;
  615.    rb->InternalFormat = internalFormat;
  616.   radeon_print(RADEON_TEXTURE, RADEON_TRACE,
  617.                 "%s(%p, rb %p) \n",
  618.                 __func__, ctx, rb);
  619.  
  620.  
  621.    return GL_TRUE;
  622. }
  623.  
  624. /** Dummy function for gl_renderbuffer::AllocStorage() */
  625. static GLboolean
  626. radeon_nop_alloc_storage(struct gl_context * ctx, struct gl_renderbuffer *rb,
  627.                          GLenum internalFormat, GLuint width, GLuint height)
  628. {
  629.    _mesa_problem(ctx, "radeon_op_alloc_storage should never be called.");
  630.    return GL_FALSE;
  631. }
  632.  
  633.  
  634. /**
  635.  * Create a renderbuffer for a window's color, depth and/or stencil buffer.
  636.  * Not used for user-created renderbuffers.
  637.  */
  638. struct radeon_renderbuffer *
  639. radeon_create_renderbuffer(gl_format format, __DRIdrawable *driDrawPriv)
  640. {
  641.     struct radeon_renderbuffer *rrb;
  642.     struct gl_renderbuffer *rb;
  643.  
  644.     rrb = CALLOC_STRUCT(radeon_renderbuffer);
  645.  
  646.     radeon_print(RADEON_TEXTURE, RADEON_TRACE,
  647.                 "%s( rrb %p ) \n",
  648.                 __func__, rrb);
  649.  
  650.     if (!rrb)
  651.         return NULL;
  652.  
  653.     rb = &rrb->base.Base;
  654.  
  655.     _mesa_init_renderbuffer(rb, 0);
  656.     rb->ClassID = RADEON_RB_CLASS;
  657.     rb->Format = format;
  658.     rb->_BaseFormat = _mesa_get_format_base_format(format);
  659.     rb->InternalFormat = _mesa_get_format_base_format(format);
  660.  
  661.     rrb->dPriv = driDrawPriv;
  662.  
  663.     rb->Delete = radeon_delete_renderbuffer;
  664.     rb->AllocStorage = radeon_alloc_window_storage;
  665.  
  666.     rrb->bo = NULL;
  667.     return rrb;
  668. }
  669.  
  670. static struct gl_renderbuffer *
  671. radeon_new_renderbuffer(struct gl_context * ctx, GLuint name)
  672. {
  673.   struct radeon_renderbuffer *rrb;
  674.   struct gl_renderbuffer *rb;
  675.  
  676.  
  677.   rrb = CALLOC_STRUCT(radeon_renderbuffer);
  678.  
  679.   radeon_print(RADEON_TEXTURE, RADEON_TRACE,
  680.                 "%s(%p, rrb %p) \n",
  681.                 __func__, ctx, rrb);
  682.  
  683.   if (!rrb)
  684.     return NULL;
  685.  
  686.   rb = &rrb->base.Base;
  687.  
  688.   _mesa_init_renderbuffer(rb, name);
  689.   rb->ClassID = RADEON_RB_CLASS;
  690.   rb->Delete = radeon_delete_renderbuffer;
  691.   rb->AllocStorage = radeon_alloc_renderbuffer_storage;
  692.  
  693.   return rb;
  694. }
  695.  
  696. static void
  697. radeon_bind_framebuffer(struct gl_context * ctx, GLenum target,
  698.                        struct gl_framebuffer *fb, struct gl_framebuffer *fbread)
  699. {
  700.   radeon_print(RADEON_TEXTURE, RADEON_TRACE,
  701.                 "%s(%p, fb %p, target %s) \n",
  702.                 __func__, ctx, fb,
  703.                 _mesa_lookup_enum_by_nr(target));
  704.  
  705.    if (target == GL_FRAMEBUFFER_EXT || target == GL_DRAW_FRAMEBUFFER_EXT) {
  706.       radeon_draw_buffer(ctx, fb);
  707.    }
  708.    else {
  709.       /* don't need to do anything if target == GL_READ_FRAMEBUFFER_EXT */
  710.    }
  711. }
  712.  
  713. static void
  714. radeon_framebuffer_renderbuffer(struct gl_context * ctx,
  715.                                struct gl_framebuffer *fb,
  716.                                GLenum attachment, struct gl_renderbuffer *rb)
  717. {
  718.  
  719.         if (ctx->Driver.Flush)
  720.                 ctx->Driver.Flush(ctx); /* +r6/r7 */
  721.  
  722.         radeon_print(RADEON_TEXTURE, RADEON_TRACE,
  723.                 "%s(%p, fb %p, rb %p) \n",
  724.                 __func__, ctx, fb, rb);
  725.  
  726.    _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb);
  727.    radeon_draw_buffer(ctx, fb);
  728. }
  729.  
  730. static GLboolean
  731. radeon_update_wrapper(struct gl_context *ctx, struct radeon_renderbuffer *rrb,
  732.                      struct gl_texture_image *texImage)
  733. {
  734.         struct gl_renderbuffer *rb = &rrb->base.Base;
  735.  
  736.         radeon_print(RADEON_TEXTURE, RADEON_TRACE,
  737.                 "%s(%p, rrb %p, texImage %p, texFormat %s) \n",
  738.                 __func__, ctx, rrb, texImage, _mesa_get_format_name(texImage->TexFormat));
  739.  
  740.         rrb->cpp = _mesa_get_format_bytes(texImage->TexFormat);
  741.         rrb->pitch = texImage->Width * rrb->cpp;
  742.         rb->Format = texImage->TexFormat;
  743.         rb->InternalFormat = texImage->InternalFormat;
  744.         rb->_BaseFormat = _mesa_base_fbo_format(ctx, rb->InternalFormat);
  745.         rb->Width = texImage->Width;
  746.         rb->Height = texImage->Height;
  747.         rb->Delete = radeon_delete_renderbuffer;
  748.         rb->AllocStorage = radeon_nop_alloc_storage;
  749.  
  750.         return GL_TRUE;
  751. }
  752.  
  753. static void
  754. radeon_render_texture(struct gl_context * ctx,
  755.                      struct gl_framebuffer *fb,
  756.                      struct gl_renderbuffer_attachment *att)
  757. {
  758.    struct gl_renderbuffer *rb = att->Renderbuffer;
  759.    struct gl_texture_image *newImage = rb->TexImage;
  760.    struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb);
  761.    radeon_texture_image *radeon_image;
  762.    GLuint imageOffset;
  763.  
  764.   radeon_print(RADEON_TEXTURE, RADEON_TRACE,
  765.                 "%s(%p, fb %p, rrb %p, att %p)\n",
  766.                 __func__, ctx, fb, rrb, att);
  767.  
  768.    (void) fb;
  769.  
  770.    ASSERT(newImage);
  771.  
  772.    radeon_image = (radeon_texture_image *)newImage;
  773.  
  774.    if (!radeon_image->mt) {
  775.       /* Fallback on drawing to a texture without a miptree.
  776.        */
  777.       _swrast_render_texture(ctx, fb, att);
  778.       return;
  779.    }
  780.  
  781.    if (!radeon_update_wrapper(ctx, rrb, newImage)) {
  782.        _swrast_render_texture(ctx, fb, att);
  783.        return;
  784.    }
  785.  
  786.    DBG("Begin render texture tid %lx tex=%u w=%d h=%d refcount=%d\n",
  787.        _glthread_GetID(),
  788.        att->Texture->Name, newImage->Width, newImage->Height,
  789.        rb->RefCount);
  790.  
  791.    /* point the renderbufer's region to the texture image region */
  792.    if (rrb->bo != radeon_image->mt->bo) {
  793.       if (rrb->bo)
  794.         radeon_bo_unref(rrb->bo);
  795.       rrb->bo = radeon_image->mt->bo;
  796.       radeon_bo_ref(rrb->bo);
  797.    }
  798.  
  799.    /* compute offset of the particular 2D image within the texture region */
  800.    imageOffset = radeon_miptree_image_offset(radeon_image->mt,
  801.                                             att->CubeMapFace,
  802.                                             att->TextureLevel);
  803.  
  804.    if (att->Texture->Target == GL_TEXTURE_3D) {
  805.       imageOffset += radeon_image->mt->levels[att->TextureLevel].rowstride *
  806.                      radeon_image->mt->levels[att->TextureLevel].height *
  807.                      att->Zoffset;
  808.    }
  809.  
  810.    /* store that offset in the region, along with the correct pitch for
  811.     * the image we are rendering to */
  812.    rrb->draw_offset = imageOffset;
  813.    rrb->pitch = radeon_image->mt->levels[att->TextureLevel].rowstride;
  814.    radeon_image->used_as_render_target = GL_TRUE;
  815.  
  816.    /* update drawing region, etc */
  817.    radeon_draw_buffer(ctx, fb);
  818. }
  819.  
  820. static void
  821. radeon_finish_render_texture(struct gl_context *ctx, struct gl_renderbuffer *rb)
  822. {
  823.     struct gl_texture_image *image = rb->TexImage;
  824.     radeon_texture_image *radeon_image = (radeon_texture_image *)image;
  825.  
  826.     if (radeon_image)
  827.         radeon_image->used_as_render_target = GL_FALSE;
  828.  
  829.     if (ctx->Driver.Flush)
  830.         ctx->Driver.Flush(ctx); /* +r6/r7 */
  831. }
  832. static void
  833. radeon_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)
  834. {
  835.         radeonContextPtr radeon = RADEON_CONTEXT(ctx);
  836.         gl_format mesa_format;
  837.         int i;
  838.  
  839.         for (i = -2; i < (GLint) ctx->Const.MaxColorAttachments; i++) {
  840.                 struct gl_renderbuffer_attachment *att;
  841.                 if (i == -2) {
  842.                         att = &fb->Attachment[BUFFER_DEPTH];
  843.                 } else if (i == -1) {
  844.                         att = &fb->Attachment[BUFFER_STENCIL];
  845.                 } else {
  846.                         att = &fb->Attachment[BUFFER_COLOR0 + i];
  847.                 }
  848.  
  849.                 if (att->Type == GL_TEXTURE) {
  850.                         mesa_format = att->Renderbuffer->TexImage->TexFormat;
  851.                 } else {
  852.                         /* All renderbuffer formats are renderable, but not sampable */
  853.                         continue;
  854.                 }
  855.  
  856.                 if (!radeon->vtbl.is_format_renderable(mesa_format)){
  857.                         fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED;
  858.                         radeon_print(RADEON_TEXTURE, RADEON_TRACE,
  859.                                                 "%s: HW doesn't support format %s as output format of attachment %d\n",
  860.                                                 __FUNCTION__, _mesa_get_format_name(mesa_format), i);
  861.                         return;
  862.                 }
  863.         }
  864. }
  865.  
  866. void radeon_fbo_init(struct radeon_context *radeon)
  867. {
  868.   radeon->glCtx.Driver.NewFramebuffer = radeon_new_framebuffer;
  869.   radeon->glCtx.Driver.NewRenderbuffer = radeon_new_renderbuffer;
  870.   radeon->glCtx.Driver.MapRenderbuffer = radeon_map_renderbuffer;
  871.   radeon->glCtx.Driver.UnmapRenderbuffer = radeon_unmap_renderbuffer;
  872.   radeon->glCtx.Driver.BindFramebuffer = radeon_bind_framebuffer;
  873.   radeon->glCtx.Driver.FramebufferRenderbuffer = radeon_framebuffer_renderbuffer;
  874.   radeon->glCtx.Driver.RenderTexture = radeon_render_texture;
  875.   radeon->glCtx.Driver.FinishRenderTexture = radeon_finish_render_texture;
  876.   radeon->glCtx.Driver.ValidateFramebuffer = radeon_validate_framebuffer;
  877.   radeon->glCtx.Driver.BlitFramebuffer = _mesa_meta_BlitFramebuffer;
  878.   radeon->glCtx.Driver.EGLImageTargetRenderbufferStorage =
  879.           radeon_image_target_renderbuffer_storage;
  880. }
  881.  
  882.  
  883. void radeon_renderbuffer_set_bo(struct radeon_renderbuffer *rb,
  884.                                 struct radeon_bo *bo)
  885. {
  886.   struct radeon_bo *old;
  887.   old = rb->bo;
  888.   rb->bo = bo;
  889.   radeon_bo_ref(bo);
  890.   if (old)
  891.     radeon_bo_unref(old);
  892. }
  893.