radeon_fbo.c revision 8a600836766716df684f2ab1eeafdcbec4b0f019
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/mtypes.h"
32#include "main/fbobject.h"
33#include "main/framebuffer.h"
34#include "main/renderbuffer.h"
35#include "main/context.h"
36#include "main/texformat.h"
37#include "main/texrender.h"
38
39#include "radeon_common.h"
40#include "radeon_mipmap_tree.h"
41
42#define FILE_DEBUG_FLAG DEBUG_TEXTURE
43#define DBG(...) do {                                           \
44        if (RADEON_DEBUG & FILE_DEBUG_FLAG)                      \
45                _mesa_printf(__VA_ARGS__);                      \
46} while(0)
47
48static struct gl_framebuffer *
49radeon_new_framebuffer(GLcontext *ctx, GLuint name)
50{
51  return _mesa_new_framebuffer(ctx, name);
52}
53
54static void
55radeon_delete_renderbuffer(struct gl_renderbuffer *rb)
56{
57  GET_CURRENT_CONTEXT(ctx);
58  struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb);
59
60  ASSERT(rrb);
61
62  if (rrb && rrb->bo) {
63    radeon_bo_unref(rrb->bo);
64  }
65
66
67  _mesa_free(rrb);
68}
69
70static void *
71radeon_get_pointer(GLcontext *ctx, struct gl_renderbuffer *rb,
72		   GLint x, GLint y)
73{
74  return NULL;
75}
76
77/**
78 * Called via glRenderbufferStorageEXT() to set the format and allocate
79 * storage for a user-created renderbuffer.
80 */
81static GLboolean
82radeon_alloc_renderbuffer_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
83                                 GLenum internalFormat,
84                                 GLuint width, GLuint height)
85{
86  struct radeon_context *radeon = RADEON_CONTEXT(ctx);
87  struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb);
88  GLboolean software_buffer = GL_FALSE;
89  int cpp;
90
91   ASSERT(rb->Name != 0);
92  switch (internalFormat) {
93   case GL_R3_G3_B2:
94   case GL_RGB4:
95   case GL_RGB5:
96      rb->_ActualFormat = GL_RGB5;
97      rb->DataType = GL_UNSIGNED_BYTE;
98      rb->RedBits = 5;
99      rb->GreenBits = 6;
100      rb->BlueBits = 5;
101      cpp = 2;
102      break;
103   case GL_RGB:
104   case GL_RGB8:
105   case GL_RGB10:
106   case GL_RGB12:
107   case GL_RGB16:
108      rb->_ActualFormat = GL_RGB8;
109      rb->DataType = GL_UNSIGNED_BYTE;
110      rb->RedBits = 8;
111      rb->GreenBits = 8;
112      rb->BlueBits = 8;
113      rb->AlphaBits = 0;
114      cpp = 4;
115      break;
116   case GL_RGBA:
117   case GL_RGBA2:
118   case GL_RGBA4:
119   case GL_RGB5_A1:
120   case GL_RGBA8:
121   case GL_RGB10_A2:
122   case GL_RGBA12:
123   case GL_RGBA16:
124      rb->_ActualFormat = GL_RGBA8;
125      rb->DataType = GL_UNSIGNED_BYTE;
126      rb->RedBits = 8;
127      rb->GreenBits = 8;
128      rb->BlueBits = 8;
129      rb->AlphaBits = 8;
130      cpp = 4;
131      break;
132   case GL_STENCIL_INDEX:
133   case GL_STENCIL_INDEX1_EXT:
134   case GL_STENCIL_INDEX4_EXT:
135   case GL_STENCIL_INDEX8_EXT:
136   case GL_STENCIL_INDEX16_EXT:
137      /* alloc a depth+stencil buffer */
138      rb->_ActualFormat = GL_DEPTH24_STENCIL8_EXT;
139      rb->DataType = GL_UNSIGNED_INT_24_8_EXT;
140      rb->StencilBits = 8;
141      cpp = 4;
142      break;
143   case GL_DEPTH_COMPONENT16:
144      rb->_ActualFormat = GL_DEPTH_COMPONENT16;
145      rb->DataType = GL_UNSIGNED_SHORT;
146      rb->DepthBits = 16;
147      cpp = 2;
148      break;
149   case GL_DEPTH_COMPONENT:
150   case GL_DEPTH_COMPONENT24:
151   case GL_DEPTH_COMPONENT32:
152      rb->_ActualFormat = GL_DEPTH24_STENCIL8_EXT;
153      rb->DataType = GL_UNSIGNED_INT_24_8_EXT;
154      rb->DepthBits = 24;
155      cpp = 4;
156      break;
157   case GL_DEPTH_STENCIL_EXT:
158   case GL_DEPTH24_STENCIL8_EXT:
159      rb->_ActualFormat = GL_DEPTH24_STENCIL8_EXT;
160      rb->DataType = GL_UNSIGNED_INT_24_8_EXT;
161      rb->DepthBits = 24;
162      rb->StencilBits = 8;
163      cpp = 4;
164      break;
165   default:
166      _mesa_problem(ctx,
167                    "Unexpected format in intel_alloc_renderbuffer_storage");
168      return GL_FALSE;
169   }
170
171  radeonFlush(ctx);
172
173  if (rrb->bo)
174    radeon_bo_unref(rrb->bo);
175
176
177   if (software_buffer) {
178      return _mesa_soft_renderbuffer_storage(ctx, rb, internalFormat,
179                                             width, height);
180   }
181   else {
182     /* TODO Alloc a BO */
183     uint32_t size = width * height * cpp;
184
185     rrb->pitch = width * cpp;
186     rrb->cpp = cpp;
187     rrb->bo = radeon_bo_open(radeon->radeonScreen->bom,
188			      0,
189			      size,
190			      0,
191			      RADEON_GEM_DOMAIN_VRAM,
192			      0);
193     //     rrb->bo = radeon_bo_open();
194     rb->Width = width;
195     rb->Height = height;
196       return GL_TRUE;
197   }
198
199}
200
201
202/**
203 * Called for each hardware renderbuffer when a _window_ is resized.
204 * Just update fields.
205 * Not used for user-created renderbuffers!
206 */
207static GLboolean
208radeon_alloc_window_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
209                           GLenum internalFormat, GLuint width, GLuint height)
210{
211   ASSERT(rb->Name == 0);
212   rb->Width = width;
213   rb->Height = height;
214   rb->_ActualFormat = internalFormat;
215
216   return GL_TRUE;
217}
218
219
220static void
221radeon_resize_buffers(GLcontext *ctx, struct gl_framebuffer *fb,
222		     GLuint width, GLuint height)
223{
224     struct radeon_framebuffer *radeon_fb = (struct radeon_framebuffer*)fb;
225   int i;
226
227   _mesa_resize_framebuffer(ctx, fb, width, height);
228
229   fb->Initialized = GL_TRUE; /* XXX remove someday */
230
231   if (fb->Name != 0) {
232      return;
233   }
234
235   /* Make sure all window system renderbuffers are up to date */
236   for (i = 0; i < 2; i++) {
237      struct gl_renderbuffer *rb = &radeon_fb->color_rb[i]->base;
238
239      /* only resize if size is changing */
240      if (rb && (rb->Width != width || rb->Height != height)) {
241	 rb->AllocStorage(ctx, rb, rb->InternalFormat, width, height);
242      }
243   }
244}
245
246
247/** Dummy function for gl_renderbuffer::AllocStorage() */
248static GLboolean
249radeon_nop_alloc_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
250			 GLenum internalFormat, GLuint width, GLuint height)
251{
252   _mesa_problem(ctx, "radeon_op_alloc_storage should never be called.");
253   return GL_FALSE;
254}
255
256struct gl_renderbuffer *
257radeon_create_renderbuffer(GLenum format, __DRIdrawablePrivate *driDrawPriv)
258{
259    struct radeon_renderbuffer *rrb;
260
261    rrb = CALLOC_STRUCT(radeon_renderbuffer);
262    if (!rrb)
263	return NULL;
264
265    _mesa_init_renderbuffer(&rrb->base, 0);
266    rrb->base.ClassID = RADEON_RB_CLASS;
267
268    /* XXX format junk */
269    switch (format) {
270	case GL_RGB5:
271	    rrb->base._ActualFormat = GL_RGB5;
272	    rrb->base._BaseFormat = GL_RGBA;
273	    rrb->base.RedBits = 5;
274	    rrb->base.GreenBits = 6;
275	    rrb->base.BlueBits = 5;
276	    rrb->base.DataType = GL_UNSIGNED_BYTE;
277	    break;
278	case GL_RGBA8:
279	    rrb->base._ActualFormat = GL_RGBA8;
280	    rrb->base._BaseFormat = GL_RGBA;
281	    rrb->base.RedBits = 8;
282	    rrb->base.GreenBits = 8;
283	    rrb->base.BlueBits = 8;
284	    rrb->base.AlphaBits = 8;
285	    rrb->base.DataType = GL_UNSIGNED_BYTE;
286	    break;
287	case GL_STENCIL_INDEX8_EXT:
288	    rrb->base._ActualFormat = GL_STENCIL_INDEX8_EXT;
289	    rrb->base._BaseFormat = GL_STENCIL_INDEX;
290	    rrb->base.StencilBits = 8;
291	    rrb->base.DataType = GL_UNSIGNED_BYTE;
292	    break;
293	case GL_DEPTH_COMPONENT16:
294	    rrb->base._ActualFormat = GL_DEPTH_COMPONENT16;
295	    rrb->base._BaseFormat = GL_DEPTH_COMPONENT;
296	    rrb->base.DepthBits = 16;
297	    rrb->base.DataType = GL_UNSIGNED_SHORT;
298	    break;
299	case GL_DEPTH_COMPONENT24:
300	    rrb->base._ActualFormat = GL_DEPTH24_STENCIL8_EXT;
301	    rrb->base._BaseFormat = GL_DEPTH_COMPONENT;
302	    rrb->base.DepthBits = 24;
303	    rrb->base.DataType = GL_UNSIGNED_INT;
304	    break;
305	case GL_DEPTH24_STENCIL8_EXT:
306	    rrb->base._ActualFormat = GL_DEPTH24_STENCIL8_EXT;
307	    rrb->base._BaseFormat = GL_DEPTH_STENCIL_EXT;
308	    rrb->base.DepthBits = 24;
309	    rrb->base.StencilBits = 8;
310	    rrb->base.DataType = GL_UNSIGNED_INT_24_8_EXT;
311	    break;
312	default:
313	    fprintf(stderr, "%s: Unknown format 0x%04x\n", __FUNCTION__, format);
314	    _mesa_delete_renderbuffer(&rrb->base);
315	    return NULL;
316    }
317
318    rrb->dPriv = driDrawPriv;
319    rrb->base.InternalFormat = format;
320
321    rrb->base.Delete = radeon_delete_renderbuffer;
322    rrb->base.AllocStorage = radeon_alloc_window_storage;
323    rrb->base.GetPointer = radeon_get_pointer;
324
325    rrb->bo = NULL;
326    return &rrb->base;
327}
328
329static struct gl_renderbuffer *
330radeon_new_renderbuffer(GLcontext * ctx, GLuint name)
331{
332  struct radeon_renderbuffer *rrb;
333
334  rrb = CALLOC_STRUCT(radeon_renderbuffer);
335  if (!rrb)
336    return NULL;
337
338  _mesa_init_renderbuffer(&rrb->base, name);
339  rrb->base.ClassID = RADEON_RB_CLASS;
340
341  rrb->base.Delete = radeon_delete_renderbuffer;
342  rrb->base.AllocStorage = radeon_alloc_renderbuffer_storage;
343  rrb->base.GetPointer = radeon_get_pointer;
344
345  return &rrb->base;
346}
347
348static void
349radeon_bind_framebuffer(GLcontext * ctx, GLenum target,
350                       struct gl_framebuffer *fb, struct gl_framebuffer *fbread)
351{
352   if (target == GL_FRAMEBUFFER_EXT || target == GL_DRAW_FRAMEBUFFER_EXT) {
353      radeon_draw_buffer(ctx, fb);
354   }
355   else {
356      /* don't need to do anything if target == GL_READ_FRAMEBUFFER_EXT */
357   }
358}
359
360static void
361radeon_framebuffer_renderbuffer(GLcontext * ctx,
362                               struct gl_framebuffer *fb,
363                               GLenum attachment, struct gl_renderbuffer *rb)
364{
365
366   radeonFlush(ctx);
367
368   _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb);
369   radeon_draw_buffer(ctx, fb);
370}
371
372
373static GLboolean
374radeon_update_wrapper(GLcontext *ctx, struct radeon_renderbuffer *rrb,
375		     struct gl_texture_image *texImage)
376{
377   if (texImage->TexFormat == &_mesa_texformat_argb8888) {
378      rrb->base._ActualFormat = GL_RGBA8;
379      rrb->base._BaseFormat = GL_RGBA;
380      rrb->base.DataType = GL_UNSIGNED_BYTE;
381      DBG("Render to RGBA8 texture OK\n");
382   }
383   else if (texImage->TexFormat == &_mesa_texformat_rgb565) {
384      rrb->base._ActualFormat = GL_RGB5;
385      rrb->base._BaseFormat = GL_RGB;
386      rrb->base.DataType = GL_UNSIGNED_SHORT;
387      DBG("Render to RGB5 texture OK\n");
388   }
389   else if (texImage->TexFormat == &_mesa_texformat_z16) {
390      rrb->base._ActualFormat = GL_DEPTH_COMPONENT16;
391      rrb->base._BaseFormat = GL_DEPTH_COMPONENT;
392      rrb->base.DataType = GL_UNSIGNED_SHORT;
393      DBG("Render to DEPTH16 texture OK\n");
394   }
395   else if (texImage->TexFormat == &_mesa_texformat_s8_z24) {
396      rrb->base._ActualFormat = GL_DEPTH24_STENCIL8_EXT;
397      rrb->base._BaseFormat = GL_DEPTH_STENCIL_EXT;
398      rrb->base.DataType = GL_UNSIGNED_INT_24_8_EXT;
399      DBG("Render to DEPTH_STENCIL texture OK\n");
400   }
401   else {
402      DBG("Render to texture BAD FORMAT %d\n",
403	  texImage->TexFormat->MesaFormat);
404      return GL_FALSE;
405   }
406
407   rrb->base.InternalFormat = rrb->base._ActualFormat;
408   rrb->base.Width = texImage->Width;
409   rrb->base.Height = texImage->Height;
410   rrb->base.RedBits = texImage->TexFormat->RedBits;
411   rrb->base.GreenBits = texImage->TexFormat->GreenBits;
412   rrb->base.BlueBits = texImage->TexFormat->BlueBits;
413   rrb->base.AlphaBits = texImage->TexFormat->AlphaBits;
414   rrb->base.DepthBits = texImage->TexFormat->DepthBits;
415
416   rrb->base.Delete = radeon_delete_renderbuffer;
417   rrb->base.AllocStorage = radeon_nop_alloc_storage;
418
419   return GL_TRUE;
420}
421
422
423static struct radeon_renderbuffer *
424radeon_wrap_texture(GLcontext * ctx, struct gl_texture_image *texImage)
425{
426  const GLuint name = ~0;   /* not significant, but distinct for debugging */
427  struct radeon_renderbuffer *rrb;
428
429   /* make an radeon_renderbuffer to wrap the texture image */
430   rrb = CALLOC_STRUCT(radeon_renderbuffer);
431   if (!rrb) {
432      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glFramebufferTexture");
433      return NULL;
434   }
435
436   _mesa_init_renderbuffer(&rrb->base, name);
437   rrb->base.ClassID = RADEON_RB_CLASS;
438
439   if (!radeon_update_wrapper(ctx, rrb, texImage)) {
440      _mesa_free(rrb);
441      return NULL;
442   }
443
444   return rrb;
445
446}
447static void
448radeon_render_texture(GLcontext * ctx,
449                     struct gl_framebuffer *fb,
450                     struct gl_renderbuffer_attachment *att)
451{
452   struct gl_texture_image *newImage
453      = att->Texture->Image[att->CubeMapFace][att->TextureLevel];
454   struct radeon_renderbuffer *rrb = radeon_renderbuffer(att->Renderbuffer);
455   radeon_texture_image *radeon_image;
456   GLuint imageOffset;
457
458   (void) fb;
459
460   ASSERT(newImage);
461
462   if (newImage->Border != 0) {
463      /* Fallback on drawing to a texture with a border, which won't have a
464       * miptree.
465       */
466      _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
467      _mesa_render_texture(ctx, fb, att);
468      return;
469   }
470   else if (!rrb) {
471      rrb = radeon_wrap_texture(ctx, newImage);
472      if (rrb) {
473         /* bind the wrapper to the attachment point */
474         _mesa_reference_renderbuffer(&att->Renderbuffer, &rrb->base);
475      }
476      else {
477         /* fallback to software rendering */
478         _mesa_render_texture(ctx, fb, att);
479         return;
480      }
481   }
482
483   if (!radeon_update_wrapper(ctx, rrb, newImage)) {
484       _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
485       _mesa_render_texture(ctx, fb, att);
486       return;
487   }
488
489   DBG("Begin render texture tid %x tex=%u w=%d h=%d refcount=%d\n",
490       _glthread_GetID(),
491       att->Texture->Name, newImage->Width, newImage->Height,
492       rrb->base.RefCount);
493
494   /* point the renderbufer's region to the texture image region */
495   radeon_image = (radeon_texture_image *)newImage;
496   if (rrb->bo != radeon_image->mt->bo) {
497      if (rrb->bo)
498  	radeon_bo_unref(rrb->bo);
499      rrb->bo = radeon_image->mt->bo;
500      radeon_bo_ref(rrb->bo);
501   }
502
503#if 0
504   /* compute offset of the particular 2D image within the texture region */
505   imageOffset = radeon_miptree_image_offset(radeon_image->mt,
506                                            att->CubeMapFace,
507                                            att->TextureLevel);
508
509   if (att->Texture->Target == GL_TEXTURE_3D) {
510      const GLuint *offsets = radeon_miptree_depth_offsets(radeon_image->mt,
511                                                          att->TextureLevel);
512      imageOffset += offsets[att->Zoffset];
513   }
514
515   /* store that offset in the region */
516   radeon_image->mt->draw_offset = imageOffset;
517#endif
518   /* update drawing region, etc */
519   radeon_draw_buffer(ctx, fb);
520}
521
522static void
523radeon_finish_render_texture(GLcontext * ctx,
524                            struct gl_renderbuffer_attachment *att)
525{
526
527}
528static void
529radeon_validate_framebuffer(GLcontext *ctx, struct gl_framebuffer *fb)
530{
531}
532
533static void
534radeon_blit_framebuffer(GLcontext *ctx,
535                       GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
536                       GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
537                       GLbitfield mask, GLenum filter)
538{
539}
540
541void radeon_fbo_init(struct radeon_context *radeon)
542{
543  radeon->glCtx->Driver.NewFramebuffer = radeon_new_framebuffer;
544  radeon->glCtx->Driver.NewRenderbuffer = radeon_new_renderbuffer;
545  radeon->glCtx->Driver.BindFramebuffer = radeon_bind_framebuffer;
546  radeon->glCtx->Driver.FramebufferRenderbuffer = radeon_framebuffer_renderbuffer;
547  radeon->glCtx->Driver.RenderTexture = radeon_render_texture;
548  radeon->glCtx->Driver.FinishRenderTexture = radeon_finish_render_texture;
549  radeon->glCtx->Driver.ResizeBuffers = radeon_resize_buffers;
550  radeon->glCtx->Driver.ValidateFramebuffer = radeon_validate_framebuffer;
551  radeon->glCtx->Driver.BlitFramebuffer = radeon_blit_framebuffer;
552}
553
554
555
556