radeon_fbo.c revision c2711cdfb68d92ede740e2cc1fd7d78f604dc201
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
50static struct gl_framebuffer *
51radeon_new_framebuffer(struct gl_context *ctx, GLuint name)
52{
53  return _mesa_new_framebuffer(ctx, name);
54}
55
56static void
57radeon_delete_renderbuffer(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  free(rrb);
71}
72
73static void
74radeon_map_renderbuffer(struct gl_context *ctx,
75		       struct gl_renderbuffer *rb,
76		       GLuint x, GLuint y, GLuint w, GLuint h,
77		       GLbitfield mode,
78		       GLubyte **out_map,
79		       GLint *out_stride)
80{
81   struct radeon_context *const rmesa = RADEON_CONTEXT(ctx);
82   struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb);
83   GLubyte *map;
84   GLboolean ok;
85   int stride, ret;
86
87   assert(rrb && rrb->bo);
88
89   /* Make a temporary buffer and blit the current contents of the renderbuffer
90    * out to it.  This gives us linear access to the buffer, instead of having
91    * to do detiling in software.
92    */
93   assert(!rrb->map_bo);
94   rrb->map_bo = radeon_bo_open(rmesa->radeonScreen->bom, 0,
95				rrb->pitch * h, 4,
96				RADEON_GEM_DOMAIN_GTT, 0);
97   rrb->map_mode = mode;
98   rrb->map_x = x;
99   rrb->map_y = y;
100   rrb->map_w = w;
101   rrb->map_h = h;
102
103   ok = rmesa->vtbl.check_blit(rb->Format);
104   assert(ok);
105
106   ok = rmesa->vtbl.blit(ctx, rrb->bo, rrb->draw_offset,
107			 rb->Format, rrb->pitch / rrb->cpp,
108			 rb->Width, rb->Height,
109			 x, y,
110			 rrb->map_bo, 0,
111			 rb->Format, rrb->pitch / rrb->cpp,
112			 w, h,
113			 0, 0,
114			 w, h,
115			 GL_FALSE);
116   assert(ok);
117
118   radeon_bo_wait(rrb->map_bo);
119   ret = radeon_bo_map(rrb->map_bo, !!(mode & GL_MAP_WRITE_BIT));
120   assert(!ret);
121
122   map = rrb->map_bo->ptr;
123   stride = rrb->pitch;
124
125   if (rb->Name == 0) {
126      map += stride * (rb->Height - 1);
127      stride = -stride;
128   }
129
130   map += x * _mesa_get_format_bytes(rb->Format);
131   map += (int)y * stride;
132
133   *out_map = map;
134   *out_stride = stride;
135}
136
137static void
138radeon_unmap_renderbuffer(struct gl_context *ctx,
139			  struct gl_renderbuffer *rb)
140{
141   struct radeon_context *const rmesa = RADEON_CONTEXT(ctx);
142   struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb);
143   GLboolean ok;
144
145   radeon_bo_unmap(rrb->map_bo);
146
147   if (rrb->map_mode & GL_MAP_WRITE_BIT) {
148      ok = rmesa->vtbl.blit(ctx, rrb->map_bo, 0,
149			    rb->Format, rrb->pitch / rrb->cpp,
150			    rrb->map_w, rrb->map_h,
151			    0, 0,
152			    rrb->bo, rrb->draw_offset,
153			    rb->Format, rrb->pitch / rrb->cpp,
154			    rb->Width, rb->Height,
155			    rrb->map_x, rrb->map_y,
156			    rrb->map_w, rrb->map_h,
157			    GL_FALSE);
158      assert(ok);
159   }
160
161   radeon_bo_unref(rrb->map_bo);
162   rrb->map_bo = NULL;
163}
164
165static void *
166radeon_get_pointer(struct gl_context *ctx, struct gl_renderbuffer *rb,
167		   GLint x, GLint y)
168{
169  radeon_print(RADEON_TEXTURE, RADEON_TRACE,
170		"%s(%p, rb %p) \n",
171		__func__, ctx, rb);
172
173  return NULL;
174}
175
176/**
177 * Called via glRenderbufferStorageEXT() to set the format and allocate
178 * storage for a user-created renderbuffer.
179 */
180static GLboolean
181radeon_alloc_renderbuffer_storage(struct gl_context * ctx, struct gl_renderbuffer *rb,
182                                 GLenum internalFormat,
183                                 GLuint width, GLuint height)
184{
185  struct radeon_context *radeon = RADEON_CONTEXT(ctx);
186  struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb);
187  uint32_t size, pitch;
188  int cpp;
189
190  radeon_print(RADEON_TEXTURE, RADEON_TRACE,
191		"%s(%p, rb %p) \n",
192		__func__, ctx, rb);
193
194   ASSERT(rb->Name != 0);
195  switch (internalFormat) {
196   case GL_R3_G3_B2:
197   case GL_RGB4:
198   case GL_RGB5:
199      rb->Format = _radeon_texformat_rgb565;
200      rb->DataType = GL_UNSIGNED_BYTE;
201      cpp = 2;
202      break;
203   case GL_RGB:
204   case GL_RGB8:
205   case GL_RGB10:
206   case GL_RGB12:
207   case GL_RGB16:
208      rb->Format = _radeon_texformat_argb8888;
209      rb->DataType = GL_UNSIGNED_BYTE;
210      cpp = 4;
211      break;
212   case GL_RGBA:
213   case GL_RGBA2:
214   case GL_RGBA4:
215   case GL_RGB5_A1:
216   case GL_RGBA8:
217   case GL_RGB10_A2:
218   case GL_RGBA12:
219   case GL_RGBA16:
220      rb->Format = _radeon_texformat_argb8888;
221      rb->DataType = GL_UNSIGNED_BYTE;
222      cpp = 4;
223      break;
224   case GL_STENCIL_INDEX:
225   case GL_STENCIL_INDEX1_EXT:
226   case GL_STENCIL_INDEX4_EXT:
227   case GL_STENCIL_INDEX8_EXT:
228   case GL_STENCIL_INDEX16_EXT:
229      /* alloc a depth+stencil buffer */
230      rb->Format = MESA_FORMAT_S8_Z24;
231      rb->DataType = GL_UNSIGNED_INT_24_8_EXT;
232      cpp = 4;
233      break;
234   case GL_DEPTH_COMPONENT16:
235      rb->Format = MESA_FORMAT_Z16;
236      rb->DataType = GL_UNSIGNED_SHORT;
237      cpp = 2;
238      break;
239   case GL_DEPTH_COMPONENT:
240   case GL_DEPTH_COMPONENT24:
241   case GL_DEPTH_COMPONENT32:
242      rb->Format = MESA_FORMAT_X8_Z24;
243      rb->DataType = GL_UNSIGNED_INT;
244      cpp = 4;
245      break;
246   case GL_DEPTH_STENCIL_EXT:
247   case GL_DEPTH24_STENCIL8_EXT:
248      rb->Format = MESA_FORMAT_S8_Z24;
249      rb->DataType = GL_UNSIGNED_INT_24_8_EXT;
250      cpp = 4;
251      break;
252   default:
253      _mesa_problem(ctx,
254                    "Unexpected format in radeon_alloc_renderbuffer_storage");
255      return GL_FALSE;
256   }
257
258  rb->_BaseFormat = _mesa_base_fbo_format(ctx, internalFormat);
259
260  if (ctx->Driver.Flush)
261	  ctx->Driver.Flush(ctx); /* +r6/r7 */
262
263  if (rrb->bo)
264    radeon_bo_unref(rrb->bo);
265
266   pitch = ((cpp * width + 63) & ~63) / cpp;
267
268   if (RADEON_DEBUG & RADEON_MEMORY)
269      fprintf(stderr,"Allocating %d x %d radeon RBO (pitch %d)\n", width,
270	      height, pitch);
271
272   size = pitch * height * cpp;
273   rrb->pitch = pitch * cpp;
274   rrb->cpp = cpp;
275   rrb->bo = radeon_bo_open(radeon->radeonScreen->bom,
276			    0,
277			    size,
278			    0,
279			    RADEON_GEM_DOMAIN_VRAM,
280			    0);
281   rb->Width = width;
282   rb->Height = height;
283   return GL_TRUE;
284}
285
286#if FEATURE_OES_EGL_image
287static void
288radeon_image_target_renderbuffer_storage(struct gl_context *ctx,
289                                         struct gl_renderbuffer *rb,
290                                         void *image_handle)
291{
292   radeonContextPtr radeon = RADEON_CONTEXT(ctx);
293   struct radeon_renderbuffer *rrb;
294   __DRIscreen *screen;
295   __DRIimage *image;
296
297   screen = radeon->radeonScreen->driScreen;
298   image = screen->dri2.image->lookupEGLImage(screen, image_handle,
299					      screen->loaderPrivate);
300   if (image == NULL)
301      return;
302
303   rrb = radeon_renderbuffer(rb);
304
305   if (ctx->Driver.Flush)
306      ctx->Driver.Flush(ctx); /* +r6/r7 */
307
308   if (rrb->bo)
309      radeon_bo_unref(rrb->bo);
310   rrb->bo = image->bo;
311   radeon_bo_ref(rrb->bo);
312   fprintf(stderr, "image->bo: %p, name: %d, rbs: w %d -> p %d\n", image->bo, image->bo->handle,
313           image->width, image->pitch);
314
315   rrb->cpp = image->cpp;
316   rrb->pitch = image->pitch * image->cpp;
317
318   rb->Format = image->format;
319   rb->InternalFormat = image->internal_format;
320   rb->Width = image->width;
321   rb->Height = image->height;
322   rb->Format = image->format;
323   rb->DataType = image->data_type;
324   rb->_BaseFormat = _mesa_base_fbo_format(radeon->glCtx,
325                                           image->internal_format);
326}
327#endif
328
329/**
330 * Called for each hardware renderbuffer when a _window_ is resized.
331 * Just update fields.
332 * Not used for user-created renderbuffers!
333 */
334static GLboolean
335radeon_alloc_window_storage(struct gl_context * ctx, struct gl_renderbuffer *rb,
336                           GLenum internalFormat, GLuint width, GLuint height)
337{
338   ASSERT(rb->Name == 0);
339   rb->Width = width;
340   rb->Height = height;
341   rb->InternalFormat = internalFormat;
342  radeon_print(RADEON_TEXTURE, RADEON_TRACE,
343		"%s(%p, rb %p) \n",
344		__func__, ctx, rb);
345
346
347   return GL_TRUE;
348}
349
350
351static void
352radeon_resize_buffers(struct gl_context *ctx, struct gl_framebuffer *fb,
353		     GLuint width, GLuint height)
354{
355     struct radeon_framebuffer *radeon_fb = (struct radeon_framebuffer*)fb;
356   int i;
357
358  radeon_print(RADEON_TEXTURE, RADEON_TRACE,
359		"%s(%p, fb %p) \n",
360		__func__, ctx, fb);
361
362   _mesa_resize_framebuffer(ctx, fb, width, height);
363
364   fb->Initialized = GL_TRUE; /* XXX remove someday */
365
366   if (fb->Name != 0) {
367      return;
368   }
369
370   /* Make sure all window system renderbuffers are up to date */
371   for (i = 0; i < 2; i++) {
372      struct gl_renderbuffer *rb = &radeon_fb->color_rb[i]->base;
373
374      /* only resize if size is changing */
375      if (rb && (rb->Width != width || rb->Height != height)) {
376	 rb->AllocStorage(ctx, rb, rb->InternalFormat, width, height);
377      }
378   }
379}
380
381
382/** Dummy function for gl_renderbuffer::AllocStorage() */
383static GLboolean
384radeon_nop_alloc_storage(struct gl_context * ctx, struct gl_renderbuffer *rb,
385			 GLenum internalFormat, GLuint width, GLuint height)
386{
387   _mesa_problem(ctx, "radeon_op_alloc_storage should never be called.");
388   return GL_FALSE;
389}
390
391
392/**
393 * Create a renderbuffer for a window's color, depth and/or stencil buffer.
394 * Not used for user-created renderbuffers.
395 */
396struct radeon_renderbuffer *
397radeon_create_renderbuffer(gl_format format, __DRIdrawable *driDrawPriv)
398{
399    struct radeon_renderbuffer *rrb;
400
401    rrb = CALLOC_STRUCT(radeon_renderbuffer);
402
403    radeon_print(RADEON_TEXTURE, RADEON_TRACE,
404		"%s( rrb %p ) \n",
405		__func__, rrb);
406
407    if (!rrb)
408	return NULL;
409
410    _mesa_init_renderbuffer(&rrb->base, 0);
411    rrb->base.ClassID = RADEON_RB_CLASS;
412
413    rrb->base.Format = format;
414
415    switch (format) {
416        case MESA_FORMAT_RGB565:
417	    assert(_mesa_little_endian());
418	    rrb->base.DataType = GL_UNSIGNED_BYTE;
419	    break;
420        case MESA_FORMAT_RGB565_REV:
421	    assert(!_mesa_little_endian());
422	    rrb->base.DataType = GL_UNSIGNED_BYTE;
423	    break;
424        case MESA_FORMAT_XRGB8888:
425	    assert(_mesa_little_endian());
426	    rrb->base.DataType = GL_UNSIGNED_BYTE;
427	    break;
428        case MESA_FORMAT_XRGB8888_REV:
429	    assert(!_mesa_little_endian());
430	    rrb->base.DataType = GL_UNSIGNED_BYTE;
431	    break;
432	case MESA_FORMAT_ARGB8888:
433	    assert(_mesa_little_endian());
434	    rrb->base.DataType = GL_UNSIGNED_BYTE;
435	    break;
436	case MESA_FORMAT_ARGB8888_REV:
437	    assert(!_mesa_little_endian());
438	    rrb->base.DataType = GL_UNSIGNED_BYTE;
439	    break;
440	case MESA_FORMAT_S8:
441	    rrb->base.DataType = GL_UNSIGNED_BYTE;
442	    break;
443	case MESA_FORMAT_Z16:
444	    rrb->base.DataType = GL_UNSIGNED_SHORT;
445	    break;
446	case MESA_FORMAT_X8_Z24:
447	    rrb->base.DataType = GL_UNSIGNED_INT;
448	    break;
449	case MESA_FORMAT_S8_Z24:
450	    rrb->base.DataType = GL_UNSIGNED_INT_24_8_EXT;
451	    break;
452	default:
453	    fprintf(stderr, "%s: Unknown format %s\n",
454                    __FUNCTION__, _mesa_get_format_name(format));
455	    _mesa_delete_renderbuffer(&rrb->base);
456	    return NULL;
457    }
458    rrb->base._BaseFormat = _mesa_get_format_base_format(format);
459
460    rrb->dPriv = driDrawPriv;
461    rrb->base.InternalFormat = _mesa_get_format_base_format(format);
462
463    rrb->base.Delete = radeon_delete_renderbuffer;
464    rrb->base.AllocStorage = radeon_alloc_window_storage;
465    rrb->base.GetPointer = radeon_get_pointer;
466
467    rrb->bo = NULL;
468    return rrb;
469}
470
471static struct gl_renderbuffer *
472radeon_new_renderbuffer(struct gl_context * ctx, GLuint name)
473{
474  struct radeon_renderbuffer *rrb;
475
476  rrb = CALLOC_STRUCT(radeon_renderbuffer);
477
478  radeon_print(RADEON_TEXTURE, RADEON_TRACE,
479		"%s(%p, rrb %p) \n",
480		__func__, ctx, rrb);
481
482  if (!rrb)
483    return NULL;
484
485  _mesa_init_renderbuffer(&rrb->base, name);
486  rrb->base.ClassID = RADEON_RB_CLASS;
487
488  rrb->base.Delete = radeon_delete_renderbuffer;
489  rrb->base.AllocStorage = radeon_alloc_renderbuffer_storage;
490  rrb->base.GetPointer = radeon_get_pointer;
491
492  return &rrb->base;
493}
494
495static void
496radeon_bind_framebuffer(struct gl_context * ctx, GLenum target,
497                       struct gl_framebuffer *fb, struct gl_framebuffer *fbread)
498{
499  radeon_print(RADEON_TEXTURE, RADEON_TRACE,
500		"%s(%p, fb %p, target %s) \n",
501		__func__, ctx, fb,
502		_mesa_lookup_enum_by_nr(target));
503
504   if (target == GL_FRAMEBUFFER_EXT || target == GL_DRAW_FRAMEBUFFER_EXT) {
505      radeon_draw_buffer(ctx, fb);
506   }
507   else {
508      /* don't need to do anything if target == GL_READ_FRAMEBUFFER_EXT */
509   }
510}
511
512static void
513radeon_framebuffer_renderbuffer(struct gl_context * ctx,
514                               struct gl_framebuffer *fb,
515                               GLenum attachment, struct gl_renderbuffer *rb)
516{
517
518	if (ctx->Driver.Flush)
519		ctx->Driver.Flush(ctx); /* +r6/r7 */
520
521	radeon_print(RADEON_TEXTURE, RADEON_TRACE,
522		"%s(%p, fb %p, rb %p) \n",
523		__func__, ctx, fb, rb);
524
525   _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb);
526   radeon_draw_buffer(ctx, fb);
527}
528
529static GLboolean
530radeon_update_wrapper(struct gl_context *ctx, struct radeon_renderbuffer *rrb,
531		     struct gl_texture_image *texImage)
532{
533	radeon_print(RADEON_TEXTURE, RADEON_TRACE,
534		"%s(%p, rrb %p, texImage %p, texFormat %s) \n",
535		__func__, ctx, rrb, texImage, _mesa_get_format_name(texImage->TexFormat));
536
537	switch (texImage->TexFormat) {
538		case MESA_FORMAT_RGBA8888:
539		case MESA_FORMAT_RGBA8888_REV:
540		case MESA_FORMAT_ARGB8888:
541		case MESA_FORMAT_ARGB8888_REV:
542		case MESA_FORMAT_XRGB8888:
543		case MESA_FORMAT_XRGB8888_REV:
544		case MESA_FORMAT_RGB565:
545		case MESA_FORMAT_RGB565_REV:
546		case MESA_FORMAT_RGBA5551:
547		case MESA_FORMAT_ARGB1555:
548		case MESA_FORMAT_ARGB1555_REV:
549		case MESA_FORMAT_ARGB4444:
550		case MESA_FORMAT_ARGB4444_REV:
551			rrb->base.DataType = GL_UNSIGNED_BYTE;
552			break;
553		case MESA_FORMAT_Z16:
554			rrb->base.DataType = GL_UNSIGNED_SHORT;
555			break;
556		case MESA_FORMAT_X8_Z24:
557			rrb->base.DataType = GL_UNSIGNED_INT;
558			break;
559		case MESA_FORMAT_S8_Z24:
560			rrb->base.DataType = GL_UNSIGNED_INT_24_8_EXT;
561			break;
562		default:
563			_mesa_problem(ctx, "Unexpected texture format in radeon_update_wrapper()");
564	}
565
566	rrb->cpp = _mesa_get_format_bytes(texImage->TexFormat);
567	rrb->pitch = texImage->Width * rrb->cpp;
568	rrb->base.Format = texImage->TexFormat;
569	rrb->base.InternalFormat = texImage->InternalFormat;
570	rrb->base._BaseFormat = _mesa_base_fbo_format(ctx, rrb->base.InternalFormat);
571	rrb->base.Width = texImage->Width;
572	rrb->base.Height = texImage->Height;
573	rrb->base.Delete = radeon_delete_renderbuffer;
574	rrb->base.AllocStorage = radeon_nop_alloc_storage;
575
576	return GL_TRUE;
577}
578
579
580static struct radeon_renderbuffer *
581radeon_wrap_texture(struct gl_context * ctx, struct gl_texture_image *texImage)
582{
583  const GLuint name = ~0;   /* not significant, but distinct for debugging */
584  struct radeon_renderbuffer *rrb;
585
586   /* make an radeon_renderbuffer to wrap the texture image */
587   rrb = CALLOC_STRUCT(radeon_renderbuffer);
588
589   radeon_print(RADEON_TEXTURE, RADEON_TRACE,
590		"%s(%p, rrb %p, texImage %p) \n",
591		__func__, ctx, rrb, texImage);
592
593   if (!rrb) {
594      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glFramebufferTexture");
595      return NULL;
596   }
597
598   _mesa_init_renderbuffer(&rrb->base, name);
599   rrb->base.ClassID = RADEON_RB_CLASS;
600
601   if (!radeon_update_wrapper(ctx, rrb, texImage)) {
602      free(rrb);
603      return NULL;
604   }
605
606   return rrb;
607
608}
609static void
610radeon_render_texture(struct gl_context * ctx,
611                     struct gl_framebuffer *fb,
612                     struct gl_renderbuffer_attachment *att)
613{
614   struct gl_texture_image *newImage
615      = att->Texture->Image[att->CubeMapFace][att->TextureLevel];
616   struct radeon_renderbuffer *rrb = radeon_renderbuffer(att->Renderbuffer);
617   radeon_texture_image *radeon_image;
618   GLuint imageOffset;
619
620  radeon_print(RADEON_TEXTURE, RADEON_TRACE,
621		"%s(%p, fb %p, rrb %p, att %p)\n",
622		__func__, ctx, fb, rrb, att);
623
624   (void) fb;
625
626   ASSERT(newImage);
627
628   radeon_image = (radeon_texture_image *)newImage;
629
630   if (!radeon_image->mt || newImage->Border != 0) {
631      /* Fallback on drawing to a texture without a miptree.
632       */
633      _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
634      _swrast_render_texture(ctx, fb, att);
635      return;
636   }
637   else if (!rrb) {
638      rrb = radeon_wrap_texture(ctx, newImage);
639      if (rrb) {
640         /* bind the wrapper to the attachment point */
641         _mesa_reference_renderbuffer(&att->Renderbuffer, &rrb->base);
642      }
643      else {
644         /* fallback to software rendering */
645         _swrast_render_texture(ctx, fb, att);
646         return;
647      }
648   }
649
650   if (!radeon_update_wrapper(ctx, rrb, newImage)) {
651       _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
652       _swrast_render_texture(ctx, fb, att);
653       return;
654   }
655
656   DBG("Begin render texture tid %lx tex=%u w=%d h=%d refcount=%d\n",
657       _glthread_GetID(),
658       att->Texture->Name, newImage->Width, newImage->Height,
659       rrb->base.RefCount);
660
661   /* point the renderbufer's region to the texture image region */
662   if (rrb->bo != radeon_image->mt->bo) {
663      if (rrb->bo)
664  	radeon_bo_unref(rrb->bo);
665      rrb->bo = radeon_image->mt->bo;
666      radeon_bo_ref(rrb->bo);
667   }
668
669   /* compute offset of the particular 2D image within the texture region */
670   imageOffset = radeon_miptree_image_offset(radeon_image->mt,
671                                            att->CubeMapFace,
672                                            att->TextureLevel);
673
674   if (att->Texture->Target == GL_TEXTURE_3D) {
675      imageOffset += radeon_image->mt->levels[att->TextureLevel].rowstride *
676                     radeon_image->mt->levels[att->TextureLevel].height *
677                     att->Zoffset;
678   }
679
680   /* store that offset in the region, along with the correct pitch for
681    * the image we are rendering to */
682   rrb->draw_offset = imageOffset;
683   rrb->pitch = radeon_image->mt->levels[att->TextureLevel].rowstride;
684
685   /* update drawing region, etc */
686   radeon_draw_buffer(ctx, fb);
687}
688
689static void
690radeon_finish_render_texture(struct gl_context * ctx,
691                            struct gl_renderbuffer_attachment *att)
692{
693
694}
695static void
696radeon_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)
697{
698	radeonContextPtr radeon = RADEON_CONTEXT(ctx);
699	gl_format mesa_format;
700	int i;
701
702	for (i = -2; i < (GLint) ctx->Const.MaxColorAttachments; i++) {
703		struct gl_renderbuffer_attachment *att;
704		if (i == -2) {
705			att = &fb->Attachment[BUFFER_DEPTH];
706		} else if (i == -1) {
707			att = &fb->Attachment[BUFFER_STENCIL];
708		} else {
709			att = &fb->Attachment[BUFFER_COLOR0 + i];
710		}
711
712		if (att->Type == GL_TEXTURE) {
713			mesa_format = att->Texture->Image[att->CubeMapFace][att->TextureLevel]->TexFormat;
714		} else {
715			/* All renderbuffer formats are renderable, but not sampable */
716			continue;
717		}
718
719		if (!radeon->vtbl.is_format_renderable(mesa_format)){
720			fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED;
721			radeon_print(RADEON_TEXTURE, RADEON_TRACE,
722						"%s: HW doesn't support format %s as output format of attachment %d\n",
723						__FUNCTION__, _mesa_get_format_name(mesa_format), i);
724			return;
725		}
726	}
727}
728
729void radeon_fbo_init(struct radeon_context *radeon)
730{
731#if FEATURE_EXT_framebuffer_object
732  radeon->glCtx->Driver.NewFramebuffer = radeon_new_framebuffer;
733  radeon->glCtx->Driver.NewRenderbuffer = radeon_new_renderbuffer;
734  radeon->glCtx->Driver.MapRenderbuffer = radeon_map_renderbuffer;
735  radeon->glCtx->Driver.UnmapRenderbuffer = radeon_unmap_renderbuffer;
736  radeon->glCtx->Driver.BindFramebuffer = radeon_bind_framebuffer;
737  radeon->glCtx->Driver.FramebufferRenderbuffer = radeon_framebuffer_renderbuffer;
738  radeon->glCtx->Driver.RenderTexture = radeon_render_texture;
739  radeon->glCtx->Driver.FinishRenderTexture = radeon_finish_render_texture;
740  radeon->glCtx->Driver.ResizeBuffers = radeon_resize_buffers;
741  radeon->glCtx->Driver.ValidateFramebuffer = radeon_validate_framebuffer;
742#endif
743#if FEATURE_EXT_framebuffer_blit
744  radeon->glCtx->Driver.BlitFramebuffer = _mesa_meta_BlitFramebuffer;
745#endif
746#if FEATURE_OES_EGL_image
747  radeon->glCtx->Driver.EGLImageTargetRenderbufferStorage =
748	  radeon_image_target_renderbuffer_storage;
749#endif
750}
751
752
753void radeon_renderbuffer_set_bo(struct radeon_renderbuffer *rb,
754				struct radeon_bo *bo)
755{
756  struct radeon_bo *old;
757  old = rb->bo;
758  rb->bo = bo;
759  radeon_bo_ref(bo);
760  if (old)
761    radeon_bo_unref(old);
762}
763