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