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