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