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/macros.h"
30 #include "main/mtypes.h"
31 #include "main/enums.h"
32 #include "main/fbobject.h"
33 #include "main/framebuffer.h"
34 #include "main/renderbuffer.h"
35 #include "main/context.h"
36 #include "swrast/swrast.h"
37 #include "drivers/common/meta.h"
38 #include "util/u_memory.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
radeon_delete_renderbuffer(struct gl_context * ctx,struct gl_renderbuffer * rb)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)
get_depth_z32(const struct radeon_renderbuffer * rrb,GLint x,GLint y)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 
get_depth_z16(const struct radeon_renderbuffer * rrb,GLint x,GLint y)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)
get_depth_z32(const struct radeon_renderbuffer * rrb,GLint x,GLint y)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 
get_depth_z16(const struct radeon_renderbuffer * rrb,GLint x,GLint y)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
radeon_map_renderbuffer_s8z24(struct gl_renderbuffer * rb,GLuint x,GLuint y,GLuint w,GLuint h,GLbitfield mode,GLubyte ** out_map,GLint * out_stride)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
radeon_map_renderbuffer_z16(struct gl_renderbuffer * rb,GLuint x,GLuint y,GLuint w,GLuint h,GLbitfield mode,GLubyte ** out_map,GLint * out_stride)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
radeon_map_renderbuffer(struct gl_context * ctx,struct gl_renderbuffer * rb,GLuint x,GLuint y,GLuint w,GLuint h,GLbitfield mode,GLubyte ** out_map,GLint * out_stride,bool flip_y)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 		       bool flip_y)
231 {
232    struct radeon_context *const rmesa = RADEON_CONTEXT(ctx);
233    struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb);
234    GLubyte *map;
235    GLboolean ok;
236    int stride, flip_stride;
237    int ret;
238    int src_x, src_y;
239 
240    /* driver does not support GL_FRAMEBUFFER_FLIP_Y_MESA */
241    assert((rb->Name == 0) == flip_y);
242 
243    if (!rrb || !rrb->bo) {
244 	   *out_map = NULL;
245 	   *out_stride = 0;
246 	   return;
247    }
248 
249    rrb->map_mode = mode;
250    rrb->map_x = x;
251    rrb->map_y = y;
252    rrb->map_w = w;
253    rrb->map_h = h;
254    rrb->map_pitch = rrb->pitch;
255 
256    ok = rmesa->vtbl.check_blit(rb->Format, rrb->pitch / rrb->cpp);
257    if (ok) {
258        if (rb->Name) {
259 	   src_x = x;
260 	   src_y = y;
261        } else {
262 	   src_x = x;
263 	   src_y = rrb->base.Base.Height - y - h;
264        }
265 
266        /* Make a temporary buffer and blit the current contents of the renderbuffer
267 	* out to it.  This gives us linear access to the buffer, instead of having
268 	* to do detiling in software.
269 	*/
270 
271        rrb->map_pitch = rrb->pitch;
272 
273        assert(!rrb->map_bo);
274        rrb->map_bo = radeon_bo_open(rmesa->radeonScreen->bom, 0,
275 				    rrb->map_pitch * h, 4,
276 				    RADEON_GEM_DOMAIN_GTT, 0);
277 
278        ok = rmesa->vtbl.blit(ctx, rrb->bo, rrb->draw_offset,
279 			     rb->Format, rrb->pitch / rrb->cpp,
280 			     rb->Width, rb->Height,
281 			     src_x, src_y,
282 			     rrb->map_bo, 0,
283 			     rb->Format, rrb->map_pitch / rrb->cpp,
284 			     w, h,
285 			     0, 0,
286 			     w, h,
287 			     GL_FALSE);
288        assert(ok);
289 
290        ret = radeon_bo_map(rrb->map_bo, !!(mode & GL_MAP_WRITE_BIT));
291        assert(!ret);
292 
293        map = rrb->map_bo->ptr;
294 
295        if (rb->Name) {
296 	   *out_map = map;
297 	   *out_stride = rrb->map_pitch;
298        } else {
299 	   *out_map = map + (h - 1) * rrb->map_pitch;
300 	   *out_stride = -rrb->map_pitch;
301        }
302        return;
303    }
304 
305    /* sw fallback flush stuff */
306    if (radeon_bo_is_referenced_by_cs(rrb->bo, rmesa->cmdbuf.cs)) {
307       radeon_firevertices(rmesa);
308    }
309 
310    if ((rmesa->radeonScreen->chip_flags & RADEON_CHIPSET_DEPTH_ALWAYS_TILED) && !rrb->has_surface) {
311        if (rb->Format == MESA_FORMAT_Z24_UNORM_S8_UINT || rb->Format == MESA_FORMAT_Z24_UNORM_X8_UINT) {
312 	   radeon_map_renderbuffer_s8z24(rb, x, y, w, h,
313 					 mode, out_map, out_stride);
314 	   return;
315        }
316        if (rb->Format == MESA_FORMAT_Z_UNORM16) {
317 	   radeon_map_renderbuffer_z16(rb, x, y, w, h,
318 				       mode, out_map, out_stride);
319 	   return;
320        }
321    }
322 
323    ret = radeon_bo_map(rrb->bo, !!(mode & GL_MAP_WRITE_BIT));
324    assert(!ret);
325    (void) ret;
326 
327    map = rrb->bo->ptr;
328    stride = rrb->map_pitch;
329 
330    if (rb->Name == 0) {
331       y = rb->Height - 1 - y;
332       flip_stride = -stride;
333    } else {
334       flip_stride = stride;
335       map += rrb->draw_offset;
336    }
337 
338    map += x * rrb->cpp;
339    map += (int)y * stride;
340 
341    *out_map = map;
342    *out_stride = flip_stride;
343 }
344 
345 static void
radeon_unmap_renderbuffer_s8z24(struct gl_context * ctx,struct gl_renderbuffer * rb)346 radeon_unmap_renderbuffer_s8z24(struct gl_context *ctx,
347 			  struct gl_renderbuffer *rb)
348 {
349    struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb);
350 
351    if (!rrb->map_buffer)
352      return;
353 
354    if (rrb->map_mode & GL_MAP_WRITE_BIT) {
355        uint32_t *untiled_s8z24_map = rrb->map_buffer;
356        uint32_t *tiled_s8z24_map;
357        int y_flip = (rb->Name == 0) ? -1 : 1;
358        int y_bias = (rb->Name == 0) ? (rb->Height - 1) : 0;
359 
360        radeon_bo_map(rrb->bo, 1);
361 
362        tiled_s8z24_map = rrb->bo->ptr;
363 
364        for (uint32_t pix_y = 0; pix_y < rrb->map_h; pix_y++) {
365 	   for (uint32_t pix_x = 0; pix_x < rrb->map_w; pix_x++) {
366 	       uint32_t flipped_y = y_flip * (int32_t)(pix_y + rrb->map_y) + y_bias;
367 	       uint32_t dst_offset = get_depth_z32(rrb, rrb->map_x + pix_x, flipped_y);
368 	       uint32_t src_offset = pix_y * rrb->map_pitch + pix_x * rrb->cpp;
369 	       tiled_s8z24_map[dst_offset/4] = untiled_s8z24_map[src_offset/4];
370 	   }
371        }
372        radeon_bo_unmap(rrb->bo);
373    }
374    free(rrb->map_buffer);
375    rrb->map_buffer = NULL;
376 }
377 
378 static void
radeon_unmap_renderbuffer_z16(struct gl_context * ctx,struct gl_renderbuffer * rb)379 radeon_unmap_renderbuffer_z16(struct gl_context *ctx,
380 			      struct gl_renderbuffer *rb)
381 {
382    struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb);
383 
384    if (!rrb->map_buffer)
385      return;
386 
387    if (rrb->map_mode & GL_MAP_WRITE_BIT) {
388        uint16_t *untiled_z16_map = rrb->map_buffer;
389        uint16_t *tiled_z16_map;
390        int y_flip = (rb->Name == 0) ? -1 : 1;
391        int y_bias = (rb->Name == 0) ? (rb->Height - 1) : 0;
392 
393        radeon_bo_map(rrb->bo, 1);
394 
395        tiled_z16_map = rrb->bo->ptr;
396 
397        for (uint32_t pix_y = 0; pix_y < rrb->map_h; pix_y++) {
398 	   for (uint32_t pix_x = 0; pix_x < rrb->map_w; pix_x++) {
399 	       uint32_t flipped_y = y_flip * (int32_t)(pix_y + rrb->map_y) + y_bias;
400 	       uint32_t dst_offset = get_depth_z16(rrb, rrb->map_x + pix_x, flipped_y);
401 	       uint32_t src_offset = pix_y * rrb->map_pitch + pix_x * rrb->cpp;
402 	       tiled_z16_map[dst_offset/2] = untiled_z16_map[src_offset/2];
403 	   }
404        }
405        radeon_bo_unmap(rrb->bo);
406    }
407    free(rrb->map_buffer);
408    rrb->map_buffer = NULL;
409 }
410 
411 
412 static void
radeon_unmap_renderbuffer(struct gl_context * ctx,struct gl_renderbuffer * rb)413 radeon_unmap_renderbuffer(struct gl_context *ctx,
414 			  struct gl_renderbuffer *rb)
415 {
416    struct radeon_context *const rmesa = RADEON_CONTEXT(ctx);
417    struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb);
418 
419    if ((rmesa->radeonScreen->chip_flags & RADEON_CHIPSET_DEPTH_ALWAYS_TILED) && !rrb->has_surface) {
420        if (rb->Format == MESA_FORMAT_Z24_UNORM_S8_UINT || rb->Format == MESA_FORMAT_Z24_UNORM_X8_UINT) {
421 	   radeon_unmap_renderbuffer_s8z24(ctx, rb);
422 	   return;
423        }
424        if (rb->Format == MESA_FORMAT_Z_UNORM16) {
425 	   radeon_unmap_renderbuffer_z16(ctx, rb);
426 	   return;
427        }
428    }
429 
430    if (!rrb->map_bo) {
431 	   if (rrb->bo)
432 		   radeon_bo_unmap(rrb->bo);
433 	   return;
434    }
435 
436    radeon_bo_unmap(rrb->map_bo);
437 
438    if (rrb->map_mode & GL_MAP_WRITE_BIT) {
439       GLboolean ok;
440       ok = rmesa->vtbl.blit(ctx, rrb->map_bo, 0,
441 			    rb->Format, rrb->map_pitch / rrb->cpp,
442 			    rrb->map_w, rrb->map_h,
443 			    0, 0,
444 			    rrb->bo, rrb->draw_offset,
445 			    rb->Format, rrb->pitch / rrb->cpp,
446 			    rb->Width, rb->Height,
447 			    rrb->map_x, rrb->map_y,
448 			    rrb->map_w, rrb->map_h,
449 			    GL_FALSE);
450       assert(ok);
451       (void) 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
radeon_alloc_renderbuffer_storage(struct gl_context * ctx,struct gl_renderbuffer * rb,GLenum internalFormat,GLuint width,GLuint height)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_Z24_UNORM_S8_UINT;
511       cpp = 4;
512       break;
513    case GL_DEPTH_COMPONENT16:
514       rb->Format = MESA_FORMAT_Z_UNORM16;
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_Z24_UNORM_X8_UINT;
521       cpp = 4;
522       break;
523    case GL_DEPTH_STENCIL_EXT:
524    case GL_DEPTH24_STENCIL8_EXT:
525       rb->Format = MESA_FORMAT_Z24_UNORM_S8_UINT;
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, 0); /* +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
radeon_image_target_renderbuffer_storage(struct gl_context * ctx,struct gl_renderbuffer * rb,void * image_handle)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, 0); /* +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
radeon_alloc_window_storage(struct gl_context * ctx,struct gl_renderbuffer * rb,GLenum internalFormat,GLuint width,GLuint height)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
radeon_nop_alloc_storage(struct gl_context * ctx,UNUSED struct gl_renderbuffer * rb,UNUSED GLenum internalFormat,UNUSED GLuint width,UNUSED GLuint height)626 radeon_nop_alloc_storage(struct gl_context * ctx,
627 			 UNUSED struct gl_renderbuffer *rb,
628 			 UNUSED GLenum internalFormat,
629 			 UNUSED GLuint width,
630 			 UNUSED GLuint height)
631 {
632    _mesa_problem(ctx, "radeon_op_alloc_storage should never be called.");
633    return GL_FALSE;
634 }
635 
636 
637 /**
638  * Create a renderbuffer for a window's color, depth and/or stencil buffer.
639  * Not used for user-created renderbuffers.
640  */
641 struct radeon_renderbuffer *
radeon_create_renderbuffer(mesa_format format,__DRIdrawable * driDrawPriv)642 radeon_create_renderbuffer(mesa_format format, __DRIdrawable *driDrawPriv)
643 {
644     struct radeon_renderbuffer *rrb;
645     struct gl_renderbuffer *rb;
646 
647     rrb = CALLOC_STRUCT(radeon_renderbuffer);
648 
649     radeon_print(RADEON_TEXTURE, RADEON_TRACE,
650 		"%s( rrb %p ) \n",
651 		__func__, rrb);
652 
653     if (!rrb)
654 	return NULL;
655 
656     rb = &rrb->base.Base;
657 
658     _mesa_init_renderbuffer(rb, 0);
659     rb->ClassID = RADEON_RB_CLASS;
660     rb->Format = format;
661     rb->_BaseFormat = _mesa_get_format_base_format(format);
662     rb->InternalFormat = _mesa_get_format_base_format(format);
663 
664     rrb->dPriv = driDrawPriv;
665 
666     rb->Delete = radeon_delete_renderbuffer;
667     rb->AllocStorage = radeon_alloc_window_storage;
668 
669     rrb->bo = NULL;
670     return rrb;
671 }
672 
673 static struct gl_renderbuffer *
radeon_new_renderbuffer(struct gl_context * ctx,GLuint name)674 radeon_new_renderbuffer(struct gl_context * ctx, GLuint name)
675 {
676   struct radeon_renderbuffer *rrb;
677   struct gl_renderbuffer *rb;
678 
679 
680   rrb = CALLOC_STRUCT(radeon_renderbuffer);
681 
682   radeon_print(RADEON_TEXTURE, RADEON_TRACE,
683 		"%s(%p, rrb %p) \n",
684 		__func__, ctx, rrb);
685 
686   if (!rrb)
687     return NULL;
688 
689   rb = &rrb->base.Base;
690 
691   _mesa_init_renderbuffer(rb, name);
692   rb->ClassID = RADEON_RB_CLASS;
693   rb->Delete = radeon_delete_renderbuffer;
694   rb->AllocStorage = radeon_alloc_renderbuffer_storage;
695 
696   return rb;
697 }
698 
699 static void
radeon_bind_framebuffer(struct gl_context * ctx,GLenum target,struct gl_framebuffer * fb,struct gl_framebuffer * fbread)700 radeon_bind_framebuffer(struct gl_context * ctx, GLenum target,
701                        struct gl_framebuffer *fb, struct gl_framebuffer *fbread)
702 {
703   radeon_print(RADEON_TEXTURE, RADEON_TRACE,
704 		"%s(%p, fb %p, target %s) \n",
705 		__func__, ctx, fb,
706 		_mesa_enum_to_string(target));
707 
708    if (target == GL_FRAMEBUFFER_EXT || target == GL_DRAW_FRAMEBUFFER_EXT) {
709       radeon_draw_buffer(ctx, fb);
710    }
711    else {
712       /* don't need to do anything if target == GL_READ_FRAMEBUFFER_EXT */
713    }
714 }
715 
716 static void
radeon_framebuffer_renderbuffer(struct gl_context * ctx,struct gl_framebuffer * fb,GLenum attachment,struct gl_renderbuffer * rb)717 radeon_framebuffer_renderbuffer(struct gl_context * ctx,
718                                struct gl_framebuffer *fb,
719                                GLenum attachment, struct gl_renderbuffer *rb)
720 {
721 
722 	if (ctx->Driver.Flush)
723 		ctx->Driver.Flush(ctx, 0); /* +r6/r7 */
724 
725 	radeon_print(RADEON_TEXTURE, RADEON_TRACE,
726 		"%s(%p, fb %p, rb %p) \n",
727 		__func__, ctx, fb, rb);
728 
729    _mesa_FramebufferRenderbuffer_sw(ctx, fb, attachment, rb);
730    radeon_draw_buffer(ctx, fb);
731 }
732 
733 static GLboolean
radeon_update_wrapper(struct gl_context * ctx,struct radeon_renderbuffer * rrb,struct gl_texture_image * texImage)734 radeon_update_wrapper(struct gl_context *ctx, struct radeon_renderbuffer *rrb,
735 		     struct gl_texture_image *texImage)
736 {
737 	struct gl_renderbuffer *rb = &rrb->base.Base;
738 
739 	radeon_print(RADEON_TEXTURE, RADEON_TRACE,
740 		"%s(%p, rrb %p, texImage %p, texFormat %s) \n",
741 		__func__, ctx, rrb, texImage, _mesa_get_format_name(texImage->TexFormat));
742 
743 	rrb->cpp = _mesa_get_format_bytes(texImage->TexFormat);
744 	rrb->pitch = texImage->Width * rrb->cpp;
745 	rb->Format = texImage->TexFormat;
746 	rb->InternalFormat = texImage->InternalFormat;
747 	rb->_BaseFormat = _mesa_get_format_base_format(rb->Format);
748 	rb->Width = texImage->Width;
749 	rb->Height = texImage->Height;
750 	rb->Delete = radeon_delete_renderbuffer;
751 	rb->AllocStorage = radeon_nop_alloc_storage;
752 
753 	return GL_TRUE;
754 }
755 
756 static void
radeon_render_texture(struct gl_context * ctx,struct gl_framebuffer * fb,struct gl_renderbuffer_attachment * att)757 radeon_render_texture(struct gl_context * ctx,
758                      struct gl_framebuffer *fb,
759                      struct gl_renderbuffer_attachment *att)
760 {
761    struct gl_renderbuffer *rb = att->Renderbuffer;
762    struct gl_texture_image *newImage = rb->TexImage;
763    struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb);
764    radeon_texture_image *radeon_image;
765    GLuint imageOffset;
766 
767   radeon_print(RADEON_TEXTURE, RADEON_TRACE,
768 		"%s(%p, fb %p, rrb %p, att %p)\n",
769 		__func__, ctx, fb, rrb, att);
770 
771    (void) fb;
772 
773    assert(newImage);
774 
775    radeon_image = (radeon_texture_image *)newImage;
776 
777    if (!radeon_image->mt) {
778       /* Fallback on drawing to a texture without a miptree.
779        */
780       _swrast_render_texture(ctx, fb, att);
781       return;
782    }
783 
784    if (!radeon_update_wrapper(ctx, rrb, newImage)) {
785        _swrast_render_texture(ctx, fb, att);
786        return;
787    }
788 
789    DBG("Begin render texture tex=%u w=%d h=%d refcount=%d\n",
790        att->Texture->Name, newImage->Width, newImage->Height,
791        rb->RefCount);
792 
793    /* point the renderbufer's region to the texture image region */
794    if (rrb->bo != radeon_image->mt->bo) {
795       if (rrb->bo)
796   	radeon_bo_unref(rrb->bo);
797       rrb->bo = radeon_image->mt->bo;
798       radeon_bo_ref(rrb->bo);
799    }
800 
801    /* compute offset of the particular 2D image within the texture region */
802    imageOffset = radeon_miptree_image_offset(radeon_image->mt,
803                                             att->CubeMapFace,
804                                             att->TextureLevel);
805 
806    if (att->Texture->Target == GL_TEXTURE_3D) {
807       imageOffset += radeon_image->mt->levels[att->TextureLevel].rowstride *
808                      radeon_image->mt->levels[att->TextureLevel].height *
809                      att->Zoffset;
810    }
811 
812    /* store that offset in the region, along with the correct pitch for
813     * the image we are rendering to */
814    rrb->draw_offset = imageOffset;
815    rrb->pitch = radeon_image->mt->levels[att->TextureLevel].rowstride;
816    radeon_image->used_as_render_target = GL_TRUE;
817 
818    /* update drawing region, etc */
819    radeon_draw_buffer(ctx, fb);
820 }
821 
822 static void
radeon_finish_render_texture(struct gl_context * ctx,struct gl_renderbuffer * rb)823 radeon_finish_render_texture(struct gl_context *ctx, struct gl_renderbuffer *rb)
824 {
825     struct gl_texture_image *image = rb->TexImage;
826     radeon_texture_image *radeon_image = (radeon_texture_image *)image;
827 
828     if (radeon_image)
829 	radeon_image->used_as_render_target = GL_FALSE;
830 
831     if (ctx->Driver.Flush)
832         ctx->Driver.Flush(ctx, 0); /* +r6/r7 */
833 }
834 static void
radeon_validate_framebuffer(struct gl_context * ctx,struct gl_framebuffer * fb)835 radeon_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)
836 {
837 	radeonContextPtr radeon = RADEON_CONTEXT(ctx);
838 	mesa_format mesa_format;
839 	int i;
840 
841 	for (i = -2; i < (GLint) ctx->Const.MaxColorAttachments; i++) {
842 		struct gl_renderbuffer_attachment *att;
843 		if (i == -2) {
844 			att = &fb->Attachment[BUFFER_DEPTH];
845 		} else if (i == -1) {
846 			att = &fb->Attachment[BUFFER_STENCIL];
847 		} else {
848 			att = &fb->Attachment[BUFFER_COLOR0 + i];
849 		}
850 
851 		if (att->Type == GL_TEXTURE) {
852 			mesa_format = att->Renderbuffer->TexImage->TexFormat;
853 		} else {
854 			/* All renderbuffer formats are renderable, but not sampable */
855 			continue;
856 		}
857 
858 		if (!radeon->vtbl.is_format_renderable(mesa_format)){
859 			fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED;
860 			radeon_print(RADEON_TEXTURE, RADEON_TRACE,
861 						"%s: HW doesn't support format %s as output format of attachment %d\n",
862 						__func__, _mesa_get_format_name(mesa_format), i);
863 			return;
864 		}
865 	}
866 }
867 
radeon_fbo_init(struct radeon_context * radeon)868 void radeon_fbo_init(struct radeon_context *radeon)
869 {
870   radeon->glCtx.Driver.NewRenderbuffer = radeon_new_renderbuffer;
871   radeon->glCtx.Driver.MapRenderbuffer = radeon_map_renderbuffer;
872   radeon->glCtx.Driver.UnmapRenderbuffer = radeon_unmap_renderbuffer;
873   radeon->glCtx.Driver.BindFramebuffer = radeon_bind_framebuffer;
874   radeon->glCtx.Driver.FramebufferRenderbuffer = radeon_framebuffer_renderbuffer;
875   radeon->glCtx.Driver.RenderTexture = radeon_render_texture;
876   radeon->glCtx.Driver.FinishRenderTexture = radeon_finish_render_texture;
877   radeon->glCtx.Driver.ValidateFramebuffer = radeon_validate_framebuffer;
878   radeon->glCtx.Driver.BlitFramebuffer = _mesa_meta_and_swrast_BlitFramebuffer;
879   radeon->glCtx.Driver.EGLImageTargetRenderbufferStorage =
880 	  radeon_image_target_renderbuffer_storage;
881 }
882 
883 
radeon_renderbuffer_set_bo(struct radeon_renderbuffer * rb,struct radeon_bo * bo)884 void radeon_renderbuffer_set_bo(struct radeon_renderbuffer *rb,
885 				struct radeon_bo *bo)
886 {
887   struct radeon_bo *old;
888   old = rb->bo;
889   rb->bo = bo;
890   radeon_bo_ref(bo);
891   if (old)
892     radeon_bo_unref(old);
893 }
894