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