radeon: fix up span function setting
[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 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
70 static void *
71 radeon_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 */
81 static GLboolean
82 radeon_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->bo = radeon_bo_open(radeon->radeonScreen->bom,
186 0,
187 size,
188 0,
189 RADEON_GEM_DOMAIN_VRAM,
190 0);
191 // rrb->bo = radeon_bo_open();
192 rb->Width = width;
193 rb->Height = height;
194 return GL_TRUE;
195 }
196
197 }
198
199
200 /**
201 * Called for each hardware renderbuffer when a _window_ is resized.
202 * Just update fields.
203 * Not used for user-created renderbuffers!
204 */
205 static GLboolean
206 radeon_alloc_window_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
207 GLenum internalFormat, GLuint width, GLuint height)
208 {
209 ASSERT(rb->Name == 0);
210 rb->Width = width;
211 rb->Height = height;
212 rb->_ActualFormat = internalFormat;
213
214 return GL_TRUE;
215 }
216
217
218 static void
219 radeon_resize_buffers(GLcontext *ctx, struct gl_framebuffer *fb,
220 GLuint width, GLuint height)
221 {
222 struct radeon_framebuffer *radeon_fb = (struct radeon_framebuffer*)fb;
223 int i;
224
225 _mesa_resize_framebuffer(ctx, fb, width, height);
226
227 fb->Initialized = GL_TRUE; /* XXX remove someday */
228
229 if (fb->Name != 0) {
230 return;
231 }
232
233 /* Make sure all window system renderbuffers are up to date */
234 for (i = 0; i < 2; i++) {
235 struct gl_renderbuffer *rb = &radeon_fb->color_rb[i]->base;
236
237 /* only resize if size is changing */
238 if (rb && (rb->Width != width || rb->Height != height)) {
239 rb->AllocStorage(ctx, rb, rb->InternalFormat, width, height);
240 }
241 }
242 }
243
244
245 /** Dummy function for gl_renderbuffer::AllocStorage() */
246 static GLboolean
247 radeon_nop_alloc_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
248 GLenum internalFormat, GLuint width, GLuint height)
249 {
250 _mesa_problem(ctx, "radeon_op_alloc_storage should never be called.");
251 return GL_FALSE;
252 }
253
254 struct gl_renderbuffer *
255 radeon_create_renderbuffer(GLenum format, __DRIdrawablePrivate *driDrawPriv)
256 {
257 struct radeon_renderbuffer *rrb;
258
259 rrb = CALLOC_STRUCT(radeon_renderbuffer);
260 if (!rrb)
261 return NULL;
262
263 _mesa_init_renderbuffer(&rrb->base, 0);
264 rrb->base.ClassID = RADEON_RB_CLASS;
265
266 /* XXX format junk */
267 switch (format) {
268 case GL_RGB5:
269 rrb->base._ActualFormat = GL_RGB5;
270 rrb->base._BaseFormat = GL_RGBA;
271 rrb->base.RedBits = 5;
272 rrb->base.GreenBits = 6;
273 rrb->base.BlueBits = 5;
274 rrb->base.DataType = GL_UNSIGNED_BYTE;
275 break;
276 case GL_RGBA8:
277 rrb->base._ActualFormat = GL_RGBA8;
278 rrb->base._BaseFormat = GL_RGBA;
279 rrb->base.RedBits = 8;
280 rrb->base.GreenBits = 8;
281 rrb->base.BlueBits = 8;
282 rrb->base.AlphaBits = 8;
283 rrb->base.DataType = GL_UNSIGNED_BYTE;
284 break;
285 case GL_STENCIL_INDEX8_EXT:
286 rrb->base._ActualFormat = GL_STENCIL_INDEX8_EXT;
287 rrb->base._BaseFormat = GL_STENCIL_INDEX;
288 rrb->base.StencilBits = 8;
289 rrb->base.DataType = GL_UNSIGNED_BYTE;
290 break;
291 case GL_DEPTH_COMPONENT16:
292 rrb->base._ActualFormat = GL_DEPTH_COMPONENT16;
293 rrb->base._BaseFormat = GL_DEPTH_COMPONENT;
294 rrb->base.DepthBits = 16;
295 rrb->base.DataType = GL_UNSIGNED_SHORT;
296 break;
297 case GL_DEPTH_COMPONENT24:
298 rrb->base._ActualFormat = GL_DEPTH24_STENCIL8_EXT;
299 rrb->base._BaseFormat = GL_DEPTH_COMPONENT;
300 rrb->base.DepthBits = 24;
301 rrb->base.DataType = GL_UNSIGNED_INT;
302 break;
303 case GL_DEPTH24_STENCIL8_EXT:
304 rrb->base._ActualFormat = GL_DEPTH24_STENCIL8_EXT;
305 rrb->base._BaseFormat = GL_DEPTH_STENCIL_EXT;
306 rrb->base.DepthBits = 24;
307 rrb->base.StencilBits = 8;
308 rrb->base.DataType = GL_UNSIGNED_INT_24_8_EXT;
309 break;
310 default:
311 fprintf(stderr, "%s: Unknown format 0x%04x\n", __FUNCTION__, format);
312 _mesa_delete_renderbuffer(&rrb->base);
313 return NULL;
314 }
315
316 rrb->dPriv = driDrawPriv;
317 rrb->base.InternalFormat = format;
318
319 rrb->base.Delete = radeon_delete_renderbuffer;
320 rrb->base.AllocStorage = radeon_alloc_window_storage;
321 rrb->base.GetPointer = radeon_get_pointer;
322
323 rrb->bo = NULL;
324 return &rrb->base;
325 }
326
327 static struct gl_renderbuffer *
328 radeon_new_renderbuffer(GLcontext * ctx, GLuint name)
329 {
330 struct radeon_renderbuffer *rrb;
331
332 rrb = CALLOC_STRUCT(radeon_renderbuffer);
333 if (!rrb)
334 return NULL;
335
336 _mesa_init_renderbuffer(&rrb->base, name);
337 rrb->base.ClassID = RADEON_RB_CLASS;
338
339 rrb->base.Delete = radeon_delete_renderbuffer;
340 rrb->base.AllocStorage = radeon_alloc_renderbuffer_storage;
341 rrb->base.GetPointer = radeon_get_pointer;
342
343 return &rrb->base;
344 }
345
346 static void
347 radeon_bind_framebuffer(GLcontext * ctx, GLenum target,
348 struct gl_framebuffer *fb, struct gl_framebuffer *fbread)
349 {
350 if (target == GL_FRAMEBUFFER_EXT || target == GL_DRAW_FRAMEBUFFER_EXT) {
351 radeon_draw_buffer(ctx, fb);
352 }
353 else {
354 /* don't need to do anything if target == GL_READ_FRAMEBUFFER_EXT */
355 }
356 }
357
358 static void
359 radeon_framebuffer_renderbuffer(GLcontext * ctx,
360 struct gl_framebuffer *fb,
361 GLenum attachment, struct gl_renderbuffer *rb)
362 {
363
364 radeonFlush(ctx);
365
366 _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb);
367 radeon_draw_buffer(ctx, fb);
368 }
369
370
371 static GLboolean
372 radeon_update_wrapper(GLcontext *ctx, struct radeon_renderbuffer *rrb,
373 struct gl_texture_image *texImage)
374 {
375 if (texImage->TexFormat == &_mesa_texformat_argb8888) {
376 rrb->base._ActualFormat = GL_RGBA8;
377 rrb->base._BaseFormat = GL_RGBA;
378 rrb->base.DataType = GL_UNSIGNED_BYTE;
379 DBG("Render to RGBA8 texture OK\n");
380 }
381 else if (texImage->TexFormat == &_mesa_texformat_rgb565) {
382 rrb->base._ActualFormat = GL_RGB5;
383 rrb->base._BaseFormat = GL_RGB;
384 rrb->base.DataType = GL_UNSIGNED_SHORT;
385 DBG("Render to RGB5 texture OK\n");
386 }
387 else if (texImage->TexFormat == &_mesa_texformat_z16) {
388 rrb->base._ActualFormat = GL_DEPTH_COMPONENT16;
389 rrb->base._BaseFormat = GL_DEPTH_COMPONENT;
390 rrb->base.DataType = GL_UNSIGNED_SHORT;
391 DBG("Render to DEPTH16 texture OK\n");
392 }
393 else if (texImage->TexFormat == &_mesa_texformat_s8_z24) {
394 rrb->base._ActualFormat = GL_DEPTH24_STENCIL8_EXT;
395 rrb->base._BaseFormat = GL_DEPTH_STENCIL_EXT;
396 rrb->base.DataType = GL_UNSIGNED_INT_24_8_EXT;
397 DBG("Render to DEPTH_STENCIL texture OK\n");
398 }
399 else {
400 DBG("Render to texture BAD FORMAT %d\n",
401 texImage->TexFormat->MesaFormat);
402 return GL_FALSE;
403 }
404
405 rrb->base.InternalFormat = rrb->base._ActualFormat;
406 rrb->base.Width = texImage->Width;
407 rrb->base.Height = texImage->Height;
408 rrb->base.RedBits = texImage->TexFormat->RedBits;
409 rrb->base.GreenBits = texImage->TexFormat->GreenBits;
410 rrb->base.BlueBits = texImage->TexFormat->BlueBits;
411 rrb->base.AlphaBits = texImage->TexFormat->AlphaBits;
412 rrb->base.DepthBits = texImage->TexFormat->DepthBits;
413
414 rrb->base.Delete = radeon_delete_renderbuffer;
415 rrb->base.AllocStorage = radeon_nop_alloc_storage;
416
417 return GL_TRUE;
418 }
419
420
421 static struct radeon_renderbuffer *
422 radeon_wrap_texture(GLcontext * ctx, struct gl_texture_image *texImage)
423 {
424 const GLuint name = ~0; /* not significant, but distinct for debugging */
425 struct radeon_renderbuffer *rrb;
426
427 /* make an radeon_renderbuffer to wrap the texture image */
428 rrb = CALLOC_STRUCT(radeon_renderbuffer);
429 if (!rrb) {
430 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glFramebufferTexture");
431 return NULL;
432 }
433
434 _mesa_init_renderbuffer(&rrb->base, name);
435 rrb->base.ClassID = RADEON_RB_CLASS;
436
437 if (!radeon_update_wrapper(ctx, rrb, texImage)) {
438 _mesa_free(rrb);
439 return NULL;
440 }
441
442 return rrb;
443
444 }
445 static void
446 radeon_render_texture(GLcontext * ctx,
447 struct gl_framebuffer *fb,
448 struct gl_renderbuffer_attachment *att)
449 {
450 struct gl_texture_image *newImage
451 = att->Texture->Image[att->CubeMapFace][att->TextureLevel];
452 struct radeon_renderbuffer *rrb = radeon_renderbuffer(att->Renderbuffer);
453 radeon_texture_image *radeon_image;
454 GLuint imageOffset;
455
456 (void) fb;
457
458 ASSERT(newImage);
459
460 if (newImage->Border != 0) {
461 /* Fallback on drawing to a texture with a border, which won't have a
462 * miptree.
463 */
464 _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
465 _mesa_render_texture(ctx, fb, att);
466 return;
467 }
468 else if (!rrb) {
469 rrb = radeon_wrap_texture(ctx, newImage);
470 if (rrb) {
471 /* bind the wrapper to the attachment point */
472 _mesa_reference_renderbuffer(&att->Renderbuffer, &rrb->base);
473 }
474 else {
475 /* fallback to software rendering */
476 _mesa_render_texture(ctx, fb, att);
477 return;
478 }
479 }
480
481 if (!radeon_update_wrapper(ctx, rrb, newImage)) {
482 _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
483 _mesa_render_texture(ctx, fb, att);
484 return;
485 }
486
487 DBG("Begin render texture tid %x tex=%u w=%d h=%d refcount=%d\n",
488 _glthread_GetID(),
489 att->Texture->Name, newImage->Width, newImage->Height,
490 rrb->base.RefCount);
491
492 /* point the renderbufer's region to the texture image region */
493 radeon_image = (radeon_texture_image *)newImage;
494 if (rrb->bo != radeon_image->mt->bo) {
495 if (rrb->bo)
496 radeon_bo_unref(rrb->bo);
497 rrb->bo = radeon_image->mt->bo;
498 radeon_bo_ref(rrb->bo);
499 }
500
501 #if 0
502 /* compute offset of the particular 2D image within the texture region */
503 imageOffset = radeon_miptree_image_offset(radeon_image->mt,
504 att->CubeMapFace,
505 att->TextureLevel);
506
507 if (att->Texture->Target == GL_TEXTURE_3D) {
508 const GLuint *offsets = radeon_miptree_depth_offsets(radeon_image->mt,
509 att->TextureLevel);
510 imageOffset += offsets[att->Zoffset];
511 }
512
513 /* store that offset in the region */
514 radeon_image->mt->draw_offset = imageOffset;
515 #endif
516 /* update drawing region, etc */
517 radeon_draw_buffer(ctx, fb);
518 }
519
520 static void
521 radeon_finish_render_texture(GLcontext * ctx,
522 struct gl_renderbuffer_attachment *att)
523 {
524
525 }
526 static void
527 radeon_validate_framebuffer(GLcontext *ctx, struct gl_framebuffer *fb)
528 {
529 }
530
531 static void
532 radeon_blit_framebuffer(GLcontext *ctx,
533 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
534 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
535 GLbitfield mask, GLenum filter)
536 {
537 }
538
539 void radeon_fbo_init(struct radeon_context *radeon)
540 {
541 radeon->glCtx->Driver.NewFramebuffer = radeon_new_framebuffer;
542 radeon->glCtx->Driver.NewRenderbuffer = radeon_new_renderbuffer;
543 radeon->glCtx->Driver.BindFramebuffer = radeon_bind_framebuffer;
544 radeon->glCtx->Driver.FramebufferRenderbuffer = radeon_framebuffer_renderbuffer;
545 radeon->glCtx->Driver.RenderTexture = radeon_render_texture;
546 radeon->glCtx->Driver.FinishRenderTexture = radeon_finish_render_texture;
547 radeon->glCtx->Driver.ResizeBuffers = radeon_resize_buffers;
548 radeon->glCtx->Driver.ValidateFramebuffer = radeon_validate_framebuffer;
549 radeon->glCtx->Driver.BlitFramebuffer = radeon_blit_framebuffer;
550 }
551
552
553