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