1
/**************************************************************************
3
* Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
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:
14
* The above copyright notice and this permission notice (including the
15
* next paragraph) shall be included in all copies or substantial portions
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.
26
**************************************************************************/
32
#include "framebuffer.h"
33
#include "renderbuffer.h"
35
#include "texformat.h"
36
#include "texrender.h"
38
#include "intel_context.h"
39
#include "intel_buffers.h"
40
#include "intel_depthstencil.h"
41
#include "intel_fbo.h"
42
#include "intel_mipmap_tree.h"
43
#include "intel_regions.h"
44
#include "intel_span.h"
47
#define FILE_DEBUG_FLAG DEBUG_FBO
49
#define INTEL_RB_CLASS 0x12345678
52
/* XXX FBO: move this to intel_context.h (inlined) */
54
* Return a gl_renderbuffer ptr casted to intel_renderbuffer.
55
* NULL will be returned if the rb isn't really an intel_renderbuffer.
56
* This is determiend by checking the ClassID.
58
struct intel_renderbuffer *
59
intel_renderbuffer(struct gl_renderbuffer *rb)
61
struct intel_renderbuffer *irb = (struct intel_renderbuffer *) rb;
62
if (irb && irb->Base.ClassID == INTEL_RB_CLASS) {
63
/*_mesa_warning(NULL, "Returning non-intel Rb\n");*/
71
struct intel_renderbuffer *
72
intel_get_renderbuffer(struct gl_framebuffer *fb, GLuint attIndex)
74
return intel_renderbuffer(fb->Attachment[attIndex].Renderbuffer);
79
intel_get_rb_region(struct gl_framebuffer *fb, GLuint attIndex)
81
struct intel_renderbuffer *irb
82
= intel_renderbuffer(fb->Attachment[attIndex].Renderbuffer);
92
* Create a new framebuffer object.
94
static struct gl_framebuffer *
95
intel_new_framebuffer(GLcontext * ctx, GLuint name)
97
/* there's no intel_framebuffer at this time, just use Mesa's class */
98
return _mesa_new_framebuffer(ctx, name);
103
intel_delete_renderbuffer(struct gl_renderbuffer *rb)
105
GET_CURRENT_CONTEXT(ctx);
106
struct intel_context *intel = intel_context(ctx);
107
struct intel_renderbuffer *irb = intel_renderbuffer(rb);
111
if (irb->PairedStencil || irb->PairedDepth) {
112
intel_unpair_depth_stencil(ctx, irb);
115
if (intel && irb->region) {
116
intel_region_release(&irb->region);
125
* Return a pointer to a specific pixel in a renderbuffer.
128
intel_get_pointer(GLcontext * ctx, struct gl_renderbuffer *rb,
131
/* By returning NULL we force all software rendering to go through
140
* Called via glRenderbufferStorageEXT() to set the format and allocate
141
* storage for a user-created renderbuffer.
144
intel_alloc_renderbuffer_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
145
GLenum internalFormat,
146
GLuint width, GLuint height)
148
struct intel_context *intel = intel_context(ctx);
149
struct intel_renderbuffer *irb = intel_renderbuffer(rb);
150
GLboolean softwareBuffer = GL_FALSE;
153
ASSERT(rb->Name != 0);
155
switch (internalFormat) {
159
rb->_ActualFormat = GL_RGB5;
160
rb->DataType = GL_UNSIGNED_BYTE;
179
rb->_ActualFormat = GL_RGBA8;
180
rb->DataType = GL_UNSIGNED_BYTE;
187
case GL_STENCIL_INDEX:
188
case GL_STENCIL_INDEX1_EXT:
189
case GL_STENCIL_INDEX4_EXT:
190
case GL_STENCIL_INDEX8_EXT:
191
case GL_STENCIL_INDEX16_EXT:
192
/* alloc a depth+stencil buffer */
193
rb->_ActualFormat = GL_DEPTH24_STENCIL8_EXT;
194
rb->DataType = GL_UNSIGNED_INT_24_8_EXT;
198
case GL_DEPTH_COMPONENT16:
199
rb->_ActualFormat = GL_DEPTH_COMPONENT16;
200
rb->DataType = GL_UNSIGNED_SHORT;
204
case GL_DEPTH_COMPONENT:
205
case GL_DEPTH_COMPONENT24:
206
case GL_DEPTH_COMPONENT32:
207
rb->_ActualFormat = GL_DEPTH24_STENCIL8_EXT;
208
rb->DataType = GL_UNSIGNED_INT_24_8_EXT;
212
case GL_DEPTH_STENCIL_EXT:
213
case GL_DEPTH24_STENCIL8_EXT:
214
rb->_ActualFormat = GL_DEPTH24_STENCIL8_EXT;
215
rb->DataType = GL_UNSIGNED_INT_24_8_EXT;
222
"Unexpected format in intel_alloc_renderbuffer_storage");
228
/* free old region */
230
intel_region_release(&irb->region);
233
/* allocate new memory region/renderbuffer */
234
if (softwareBuffer) {
235
return _mesa_soft_renderbuffer_storage(ctx, rb, internalFormat,
239
/* Choose a pitch to match hardware requirements:
241
GLuint pitch = ((cpp * width + 63) & ~63) / cpp;
243
/* alloc hardware renderbuffer */
244
DBG("Allocating %d x %d Intel RBO (pitch %d)\n", width,
247
irb->region = intel_region_alloc(intel->intelScreen, cpp, pitch, height);
249
return GL_FALSE; /* out of memory? */
251
ASSERT(irb->region->buffer);
256
/* This sets the Get/PutRow/Value functions */
257
intel_set_span_functions(&irb->Base);
266
* Called for each hardware renderbuffer when a _window_ is resized.
267
* Just update fields.
268
* Not used for user-created renderbuffers!
271
intel_alloc_window_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
272
GLenum internalFormat, GLuint width, GLuint height)
274
ASSERT(rb->Name == 0);
277
rb->_ActualFormat = internalFormat;
283
intel_nop_alloc_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
284
GLenum internalFormat, GLuint width, GLuint height)
286
_mesa_problem(ctx, "intel_op_alloc_storage should never be called.");
293
* Create a new intel_renderbuffer which corresponds to an on-screen window,
294
* not a user-created renderbuffer.
295
* \param width the screen width
296
* \param height the screen height
298
struct intel_renderbuffer *
299
intel_create_renderbuffer(GLenum intFormat, GLsizei width, GLsizei height,
300
int offset, int pitch, int cpp, void *map)
302
GET_CURRENT_CONTEXT(ctx);
304
struct intel_renderbuffer *irb;
305
const GLuint name = 0;
307
irb = CALLOC_STRUCT(intel_renderbuffer);
309
_mesa_error(ctx, GL_OUT_OF_MEMORY, "creating renderbuffer");
313
_mesa_init_renderbuffer(&irb->Base, name);
314
irb->Base.ClassID = INTEL_RB_CLASS;
318
irb->Base._ActualFormat = GL_RGB5;
319
irb->Base._BaseFormat = GL_RGBA;
320
irb->Base.RedBits = 5;
321
irb->Base.GreenBits = 6;
322
irb->Base.BlueBits = 5;
323
irb->Base.DataType = GL_UNSIGNED_BYTE;
327
irb->Base._ActualFormat = GL_RGBA8;
328
irb->Base._BaseFormat = GL_RGBA;
329
irb->Base.RedBits = 8;
330
irb->Base.GreenBits = 8;
331
irb->Base.BlueBits = 8;
332
irb->Base.AlphaBits = 8;
333
irb->Base.DataType = GL_UNSIGNED_BYTE;
336
case GL_STENCIL_INDEX8_EXT:
337
irb->Base._ActualFormat = GL_STENCIL_INDEX8_EXT;
338
irb->Base._BaseFormat = GL_STENCIL_INDEX;
339
irb->Base.StencilBits = 8;
340
irb->Base.DataType = GL_UNSIGNED_BYTE;
343
case GL_DEPTH_COMPONENT16:
344
irb->Base._ActualFormat = GL_DEPTH_COMPONENT16;
345
irb->Base._BaseFormat = GL_DEPTH_COMPONENT;
346
irb->Base.DepthBits = 16;
347
irb->Base.DataType = GL_UNSIGNED_SHORT;
350
case GL_DEPTH_COMPONENT24:
351
irb->Base._ActualFormat = GL_DEPTH24_STENCIL8_EXT;
352
irb->Base._BaseFormat = GL_DEPTH_COMPONENT;
353
irb->Base.DepthBits = 24;
354
irb->Base.DataType = GL_UNSIGNED_INT;
357
case GL_DEPTH24_STENCIL8_EXT:
358
irb->Base._ActualFormat = GL_DEPTH24_STENCIL8_EXT;
359
irb->Base._BaseFormat = GL_DEPTH_STENCIL_EXT;
360
irb->Base.DepthBits = 24;
361
irb->Base.StencilBits = 8;
362
irb->Base.DataType = GL_UNSIGNED_INT_24_8_EXT;
367
"Unexpected intFormat in intel_create_renderbuffer");
371
irb->Base.InternalFormat = intFormat;
373
/* intel-specific methods */
374
irb->Base.Delete = intel_delete_renderbuffer;
375
irb->Base.AllocStorage = intel_alloc_window_storage;
376
irb->Base.GetPointer = intel_get_pointer;
377
/* This sets the Get/PutRow/Value functions */
378
intel_set_span_functions(&irb->Base);
381
irb->pfPitch = pitch / cpp; /* in pixels */
384
irb->region = intel_region_create_static(intel,
386
offset, map, cpp, width, height);
394
* Create a new renderbuffer object.
395
* Typically called via glBindRenderbufferEXT().
397
static struct gl_renderbuffer *
398
intel_new_renderbuffer(GLcontext * ctx, GLuint name)
400
/*struct intel_context *intel = intel_context(ctx); */
401
struct intel_renderbuffer *irb;
403
irb = CALLOC_STRUCT(intel_renderbuffer);
405
_mesa_error(ctx, GL_OUT_OF_MEMORY, "creating renderbuffer");
409
_mesa_init_renderbuffer(&irb->Base, name);
410
irb->Base.ClassID = INTEL_RB_CLASS;
412
/* intel-specific methods */
413
irb->Base.Delete = intel_delete_renderbuffer;
414
irb->Base.AllocStorage = intel_alloc_renderbuffer_storage;
415
irb->Base.GetPointer = intel_get_pointer;
416
/* span routines set in alloc_storage function */
423
* Called via glBindFramebufferEXT().
426
intel_bind_framebuffer(GLcontext * ctx, GLenum target,
427
struct gl_framebuffer *fb)
429
if (target == GL_FRAMEBUFFER_EXT || target == GL_DRAW_FRAMEBUFFER_EXT) {
430
intel_draw_buffer(ctx, fb);
431
/* Integer depth range depends on depth buffer bits */
432
ctx->Driver.DepthRange(ctx, ctx->Viewport.Near, ctx->Viewport.Far);
435
/* don't need to do anything if target == GL_READ_FRAMEBUFFER_EXT */
441
* Called via glFramebufferRenderbufferEXT().
444
intel_framebuffer_renderbuffer(GLcontext * ctx,
445
struct gl_framebuffer *fb,
446
GLenum attachment, struct gl_renderbuffer *rb)
448
DBG("Intel FramebufferRenderbuffer %u %u\n", fb->Name, rb ? rb->Name : 0);
452
_mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb);
453
intel_draw_buffer(ctx, fb);
458
* When glFramebufferTexture[123]D is called this function sets up the
459
* gl_renderbuffer wrapp around the texture image.
460
* This will have the region info needed for hardware rendering.
462
static struct intel_renderbuffer *
463
intel_wrap_texture(GLcontext * ctx, struct gl_texture_image *texImage)
465
const GLuint name = ~0; /* not significant, but distinct for debugging */
466
struct intel_renderbuffer *irb;
468
/* make an intel_renderbuffer to wrap the texture image */
469
irb = CALLOC_STRUCT(intel_renderbuffer);
471
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glFramebufferTexture");
475
_mesa_init_renderbuffer(&irb->Base, name);
476
irb->Base.ClassID = INTEL_RB_CLASS;
478
if (texImage->TexFormat == &_mesa_texformat_argb8888) {
479
irb->Base._ActualFormat = GL_RGBA8;
480
irb->Base._BaseFormat = GL_RGBA;
481
DBG("Render to RGBA8 texture OK\n");
483
else if (texImage->TexFormat == &_mesa_texformat_rgb565) {
484
irb->Base._ActualFormat = GL_RGB5;
485
irb->Base._BaseFormat = GL_RGB;
486
DBG("Render to RGB5 texture OK\n");
488
else if (texImage->TexFormat == &_mesa_texformat_z16) {
489
irb->Base._ActualFormat = GL_DEPTH_COMPONENT16;
490
irb->Base._BaseFormat = GL_DEPTH_COMPONENT;
491
DBG("Render to DEPTH16 texture OK\n");
494
DBG("Render to texture BAD FORMAT %d\n",
495
texImage->TexFormat->MesaFormat);
500
irb->Base.InternalFormat = irb->Base._ActualFormat;
501
irb->Base.Width = texImage->Width;
502
irb->Base.Height = texImage->Height;
503
irb->Base.DataType = GL_UNSIGNED_BYTE; /* FBO XXX fix */
504
irb->Base.RedBits = texImage->TexFormat->RedBits;
505
irb->Base.GreenBits = texImage->TexFormat->GreenBits;
506
irb->Base.BlueBits = texImage->TexFormat->BlueBits;
507
irb->Base.AlphaBits = texImage->TexFormat->AlphaBits;
508
irb->Base.DepthBits = texImage->TexFormat->DepthBits;
510
irb->Base.Delete = intel_delete_renderbuffer;
511
irb->Base.AllocStorage = intel_nop_alloc_storage;
512
intel_set_span_functions(&irb->Base);
514
irb->RenderToTexture = GL_TRUE;
521
* Called by glFramebufferTexture[123]DEXT() (and other places) to
522
* prepare for rendering into texture memory. This might be called
523
* many times to choose different texture levels, cube faces, etc
524
* before intel_finish_render_texture() is ever called.
527
intel_render_texture(GLcontext * ctx,
528
struct gl_framebuffer *fb,
529
struct gl_renderbuffer_attachment *att)
531
struct gl_texture_image *newImage
532
= att->Texture->Image[att->CubeMapFace][att->TextureLevel];
533
struct intel_renderbuffer *irb = intel_renderbuffer(att->Renderbuffer);
534
struct intel_texture_image *intel_image;
542
irb = intel_wrap_texture(ctx, newImage);
544
/* bind the wrapper to the attachment point */
545
att->Renderbuffer = &irb->Base;
548
/* fallback to software rendering */
549
_mesa_render_texture(ctx, fb, att);
554
DBG("Begin render texture tid %x tex=%u w=%d h=%d refcount=%d\n",
556
att->Texture->Name, newImage->Width, newImage->Height,
559
/* point the renderbufer's region to the texture image region */
560
intel_image = intel_texture_image(newImage);
561
if (irb->region != intel_image->mt->region) {
563
intel_region_release(&irb->region);
564
intel_region_reference(&irb->region, intel_image->mt->region);
567
/* compute offset of the particular 2D image within the texture region */
568
imageOffset = intel_miptree_image_offset(intel_image->mt,
572
if (att->Texture->Target == GL_TEXTURE_3D) {
573
const GLuint *offsets = intel_miptree_depth_offsets(intel_image->mt,
575
imageOffset += offsets[att->Zoffset];
578
/* store that offset in the region */
579
intel_image->mt->region->draw_offset = imageOffset;
581
/* update drawing region, etc */
582
intel_draw_buffer(ctx, fb);
587
* Called by Mesa when rendering to a texture is done.
590
intel_finish_render_texture(GLcontext * ctx,
591
struct gl_renderbuffer_attachment *att)
593
struct intel_renderbuffer *irb = intel_renderbuffer(att->Renderbuffer);
595
DBG("End render texture (tid %x) tex %u\n", _glthread_GetID(), att->Texture->Name);
598
/* just release the region */
599
intel_region_release(&irb->region);
601
else if (att->Renderbuffer) {
602
/* software fallback */
603
_mesa_finish_render_texture(ctx, att);
604
/* XXX FBO: Need to unmap the buffer (or in intelSpanRenderStart???) */
610
* Do one-time context initializations related to GL_EXT_framebuffer_object.
611
* Hook in device driver functions.
614
intel_fbo_init(struct intel_context *intel)
616
intel->ctx.Driver.NewFramebuffer = intel_new_framebuffer;
617
intel->ctx.Driver.NewRenderbuffer = intel_new_renderbuffer;
618
intel->ctx.Driver.BindFramebuffer = intel_bind_framebuffer;
619
intel->ctx.Driver.FramebufferRenderbuffer = intel_framebuffer_renderbuffer;
620
intel->ctx.Driver.RenderTexture = intel_render_texture;
621
intel->ctx.Driver.FinishRenderTexture = intel_finish_render_texture;