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 **************************************************************************/
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 #include "drivers/common/meta.h"
40 #include "intel_context.h"
41 #include "intel_buffers.h"
42 #include "intel_fbo.h"
43 #include "intel_mipmap_tree.h"
44 #include "intel_regions.h"
47 #define FILE_DEBUG_FLAG DEBUG_FBO
51 * Create a new framebuffer object.
53 static struct gl_framebuffer
*
54 intel_new_framebuffer(GLcontext
* ctx
, GLuint name
)
56 /* Only drawable state in intel_framebuffer at this time, just use Mesa's
59 return _mesa_new_framebuffer(ctx
, name
);
63 /** Called by gl_renderbuffer::Delete() */
65 intel_delete_renderbuffer(struct gl_renderbuffer
*rb
)
67 GET_CURRENT_CONTEXT(ctx
);
68 struct intel_context
*intel
= intel_context(ctx
);
69 struct intel_renderbuffer
*irb
= intel_renderbuffer(rb
);
73 if (irb
->span_cache
!= NULL
)
74 _mesa_free(irb
->span_cache
);
76 if (intel
&& irb
->region
) {
77 intel_region_release(&irb
->region
);
85 * Return a pointer to a specific pixel in a renderbuffer.
88 intel_get_pointer(GLcontext
* ctx
, struct gl_renderbuffer
*rb
,
91 /* By returning NULL we force all software rendering to go through
99 * Called via glRenderbufferStorageEXT() to set the format and allocate
100 * storage for a user-created renderbuffer.
103 intel_alloc_renderbuffer_storage(GLcontext
* ctx
, struct gl_renderbuffer
*rb
,
104 GLenum internalFormat
,
105 GLuint width
, GLuint height
)
107 struct intel_context
*intel
= intel_context(ctx
);
108 struct intel_renderbuffer
*irb
= intel_renderbuffer(rb
);
109 GLboolean softwareBuffer
= GL_FALSE
;
112 ASSERT(rb
->Name
!= 0);
114 switch (internalFormat
) {
118 rb
->_ActualFormat
= GL_RGB5
;
119 rb
->DataType
= GL_UNSIGNED_BYTE
;
123 irb
->texformat
= &_mesa_texformat_rgb565
;
131 rb
->_ActualFormat
= GL_RGB8
;
132 rb
->DataType
= GL_UNSIGNED_BYTE
;
137 irb
->texformat
= &_mesa_texformat_argb8888
; /* XXX: Need xrgb8888 */
148 rb
->_ActualFormat
= GL_RGBA8
;
149 rb
->DataType
= GL_UNSIGNED_BYTE
;
154 irb
->texformat
= &_mesa_texformat_argb8888
;
157 case GL_STENCIL_INDEX
:
158 case GL_STENCIL_INDEX1_EXT
:
159 case GL_STENCIL_INDEX4_EXT
:
160 case GL_STENCIL_INDEX8_EXT
:
161 case GL_STENCIL_INDEX16_EXT
:
162 /* alloc a depth+stencil buffer */
163 rb
->_ActualFormat
= GL_DEPTH24_STENCIL8_EXT
;
164 rb
->DataType
= GL_UNSIGNED_INT_24_8_EXT
;
167 irb
->texformat
= &_mesa_texformat_s8_z24
;
169 case GL_DEPTH_COMPONENT16
:
170 rb
->_ActualFormat
= GL_DEPTH_COMPONENT16
;
171 rb
->DataType
= GL_UNSIGNED_SHORT
;
174 irb
->texformat
= &_mesa_texformat_z16
;
176 case GL_DEPTH_COMPONENT
:
177 case GL_DEPTH_COMPONENT24
:
178 case GL_DEPTH_COMPONENT32
:
179 rb
->_ActualFormat
= GL_DEPTH24_STENCIL8_EXT
;
180 rb
->DataType
= GL_UNSIGNED_INT_24_8_EXT
;
183 irb
->texformat
= &_mesa_texformat_s8_z24
;
185 case GL_DEPTH_STENCIL_EXT
:
186 case GL_DEPTH24_STENCIL8_EXT
:
187 rb
->_ActualFormat
= GL_DEPTH24_STENCIL8_EXT
;
188 rb
->DataType
= GL_UNSIGNED_INT_24_8_EXT
;
192 irb
->texformat
= &_mesa_texformat_s8_z24
;
196 "Unexpected format in intel_alloc_renderbuffer_storage");
202 /* free old region */
204 intel_region_release(&irb
->region
);
207 /* allocate new memory region/renderbuffer */
208 if (softwareBuffer
) {
209 return _mesa_soft_renderbuffer_storage(ctx
, rb
, internalFormat
,
213 /* Choose a pitch to match hardware requirements:
215 GLuint pitch
= ((cpp
* width
+ 63) & ~63) / cpp
;
217 /* alloc hardware renderbuffer */
218 DBG("Allocating %d x %d Intel RBO (pitch %d)\n", width
,
221 irb
->region
= intel_region_alloc(intel
, I915_TILING_NONE
,
222 cpp
, width
, height
, pitch
,
225 return GL_FALSE
; /* out of memory? */
227 ASSERT(irb
->region
->buffer
);
238 * Called for each hardware renderbuffer when a _window_ is resized.
239 * Just update fields.
240 * Not used for user-created renderbuffers!
243 intel_alloc_window_storage(GLcontext
* ctx
, struct gl_renderbuffer
*rb
,
244 GLenum internalFormat
, GLuint width
, GLuint height
)
246 ASSERT(rb
->Name
== 0);
249 rb
->_ActualFormat
= internalFormat
;
256 intel_resize_buffers(GLcontext
*ctx
, struct gl_framebuffer
*fb
,
257 GLuint width
, GLuint height
)
259 struct intel_framebuffer
*intel_fb
= (struct intel_framebuffer
*)fb
;
262 _mesa_resize_framebuffer(ctx
, fb
, width
, height
);
264 fb
->Initialized
= GL_TRUE
; /* XXX remove someday */
270 /* Make sure all window system renderbuffers are up to date */
271 for (i
= 0; i
< 2; i
++) {
272 struct gl_renderbuffer
*rb
= &intel_fb
->color_rb
[i
]->Base
;
274 /* only resize if size is changing */
275 if (rb
&& (rb
->Width
!= width
|| rb
->Height
!= height
)) {
276 rb
->AllocStorage(ctx
, rb
, rb
->InternalFormat
, width
, height
);
282 /** Dummy function for gl_renderbuffer::AllocStorage() */
284 intel_nop_alloc_storage(GLcontext
* ctx
, struct gl_renderbuffer
*rb
,
285 GLenum internalFormat
, GLuint width
, GLuint height
)
287 _mesa_problem(ctx
, "intel_op_alloc_storage should never be called.");
293 intel_renderbuffer_set_region(struct intel_renderbuffer
*rb
,
294 struct intel_region
*region
)
296 struct intel_region
*old
;
300 intel_region_reference(&rb
->region
, region
);
301 intel_region_release(&old
);
306 * Create a new intel_renderbuffer which corresponds to an on-screen window,
307 * not a user-created renderbuffer.
309 struct intel_renderbuffer
*
310 intel_create_renderbuffer(GLenum intFormat
)
312 GET_CURRENT_CONTEXT(ctx
);
314 struct intel_renderbuffer
*irb
;
315 const GLuint name
= 0;
317 irb
= CALLOC_STRUCT(intel_renderbuffer
);
319 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "creating renderbuffer");
323 _mesa_init_renderbuffer(&irb
->Base
, name
);
324 irb
->Base
.ClassID
= INTEL_RB_CLASS
;
328 irb
->Base
._ActualFormat
= GL_RGB5
;
329 irb
->Base
._BaseFormat
= GL_RGBA
;
330 irb
->Base
.RedBits
= 5;
331 irb
->Base
.GreenBits
= 6;
332 irb
->Base
.BlueBits
= 5;
333 irb
->Base
.DataType
= GL_UNSIGNED_BYTE
;
334 irb
->texformat
= &_mesa_texformat_rgb565
;
337 irb
->Base
._ActualFormat
= GL_RGB8
;
338 irb
->Base
._BaseFormat
= GL_RGB
;
339 irb
->Base
.RedBits
= 8;
340 irb
->Base
.GreenBits
= 8;
341 irb
->Base
.BlueBits
= 8;
342 irb
->Base
.AlphaBits
= 0;
343 irb
->Base
.DataType
= GL_UNSIGNED_BYTE
;
344 irb
->texformat
= &_mesa_texformat_argb8888
; /* XXX: Need xrgb8888 */
347 irb
->Base
._ActualFormat
= GL_RGBA8
;
348 irb
->Base
._BaseFormat
= GL_RGBA
;
349 irb
->Base
.RedBits
= 8;
350 irb
->Base
.GreenBits
= 8;
351 irb
->Base
.BlueBits
= 8;
352 irb
->Base
.AlphaBits
= 8;
353 irb
->Base
.DataType
= GL_UNSIGNED_BYTE
;
354 irb
->texformat
= &_mesa_texformat_argb8888
;
356 case GL_STENCIL_INDEX8_EXT
:
357 irb
->Base
._ActualFormat
= GL_STENCIL_INDEX8_EXT
;
358 irb
->Base
._BaseFormat
= GL_STENCIL_INDEX
;
359 irb
->Base
.StencilBits
= 8;
360 irb
->Base
.DataType
= GL_UNSIGNED_BYTE
;
361 irb
->texformat
= &_mesa_texformat_s8_z24
;
363 case GL_DEPTH_COMPONENT16
:
364 irb
->Base
._ActualFormat
= GL_DEPTH_COMPONENT16
;
365 irb
->Base
._BaseFormat
= GL_DEPTH_COMPONENT
;
366 irb
->Base
.DepthBits
= 16;
367 irb
->Base
.DataType
= GL_UNSIGNED_SHORT
;
368 irb
->texformat
= &_mesa_texformat_z16
;
370 case GL_DEPTH_COMPONENT24
:
371 irb
->Base
._ActualFormat
= GL_DEPTH24_STENCIL8_EXT
;
372 irb
->Base
._BaseFormat
= GL_DEPTH_COMPONENT
;
373 irb
->Base
.DepthBits
= 24;
374 irb
->Base
.DataType
= GL_UNSIGNED_INT
;
375 irb
->texformat
= &_mesa_texformat_s8_z24
;
377 case GL_DEPTH24_STENCIL8_EXT
:
378 irb
->Base
._ActualFormat
= GL_DEPTH24_STENCIL8_EXT
;
379 irb
->Base
._BaseFormat
= GL_DEPTH_STENCIL_EXT
;
380 irb
->Base
.DepthBits
= 24;
381 irb
->Base
.StencilBits
= 8;
382 irb
->Base
.DataType
= GL_UNSIGNED_INT_24_8_EXT
;
383 irb
->texformat
= &_mesa_texformat_s8_z24
;
387 "Unexpected intFormat in intel_create_renderbuffer");
392 irb
->Base
.InternalFormat
= intFormat
;
394 /* intel-specific methods */
395 irb
->Base
.Delete
= intel_delete_renderbuffer
;
396 irb
->Base
.AllocStorage
= intel_alloc_window_storage
;
397 irb
->Base
.GetPointer
= intel_get_pointer
;
404 * Create a new renderbuffer object.
405 * Typically called via glBindRenderbufferEXT().
407 static struct gl_renderbuffer
*
408 intel_new_renderbuffer(GLcontext
* ctx
, GLuint name
)
410 /*struct intel_context *intel = intel_context(ctx); */
411 struct intel_renderbuffer
*irb
;
413 irb
= CALLOC_STRUCT(intel_renderbuffer
);
415 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "creating renderbuffer");
419 _mesa_init_renderbuffer(&irb
->Base
, name
);
420 irb
->Base
.ClassID
= INTEL_RB_CLASS
;
422 /* intel-specific methods */
423 irb
->Base
.Delete
= intel_delete_renderbuffer
;
424 irb
->Base
.AllocStorage
= intel_alloc_renderbuffer_storage
;
425 irb
->Base
.GetPointer
= intel_get_pointer
;
426 /* span routines set in alloc_storage function */
433 * Called via glBindFramebufferEXT().
436 intel_bind_framebuffer(GLcontext
* ctx
, GLenum target
,
437 struct gl_framebuffer
*fb
, struct gl_framebuffer
*fbread
)
439 if (target
== GL_FRAMEBUFFER_EXT
|| target
== GL_DRAW_FRAMEBUFFER_EXT
) {
440 intel_draw_buffer(ctx
, fb
);
443 /* don't need to do anything if target == GL_READ_FRAMEBUFFER_EXT */
449 * Called via glFramebufferRenderbufferEXT().
452 intel_framebuffer_renderbuffer(GLcontext
* ctx
,
453 struct gl_framebuffer
*fb
,
454 GLenum attachment
, struct gl_renderbuffer
*rb
)
456 DBG("Intel FramebufferRenderbuffer %u %u\n", fb
->Name
, rb
? rb
->Name
: 0);
460 _mesa_framebuffer_renderbuffer(ctx
, fb
, attachment
, rb
);
461 intel_draw_buffer(ctx
, fb
);
466 intel_update_wrapper(GLcontext
*ctx
, struct intel_renderbuffer
*irb
,
467 struct gl_texture_image
*texImage
)
469 irb
->texformat
= texImage
->TexFormat
;
471 if (texImage
->TexFormat
== &_mesa_texformat_argb8888
) {
472 irb
->Base
._ActualFormat
= GL_RGBA8
;
473 irb
->Base
._BaseFormat
= GL_RGBA
;
474 irb
->Base
.DataType
= GL_UNSIGNED_BYTE
;
475 DBG("Render to RGBA8 texture OK\n");
477 else if (texImage
->TexFormat
== &_mesa_texformat_rgb565
) {
478 irb
->Base
._ActualFormat
= GL_RGB5
;
479 irb
->Base
._BaseFormat
= GL_RGB
;
480 irb
->Base
.DataType
= GL_UNSIGNED_BYTE
;
481 DBG("Render to RGB5 texture OK\n");
483 else if (texImage
->TexFormat
== &_mesa_texformat_argb1555
) {
484 irb
->Base
._ActualFormat
= GL_RGB5_A1
;
485 irb
->Base
._BaseFormat
= GL_RGBA
;
486 irb
->Base
.DataType
= GL_UNSIGNED_BYTE
;
487 DBG("Render to ARGB1555 texture OK\n");
489 else if (texImage
->TexFormat
== &_mesa_texformat_argb4444
) {
490 irb
->Base
._ActualFormat
= GL_RGBA4
;
491 irb
->Base
._BaseFormat
= GL_RGBA
;
492 irb
->Base
.DataType
= GL_UNSIGNED_BYTE
;
493 DBG("Render to ARGB4444 texture OK\n");
495 else if (texImage
->TexFormat
== &_mesa_texformat_z16
) {
496 irb
->Base
._ActualFormat
= GL_DEPTH_COMPONENT16
;
497 irb
->Base
._BaseFormat
= GL_DEPTH_COMPONENT
;
498 irb
->Base
.DataType
= GL_UNSIGNED_SHORT
;
499 DBG("Render to DEPTH16 texture OK\n");
501 else if (texImage
->TexFormat
== &_mesa_texformat_s8_z24
) {
502 irb
->Base
._ActualFormat
= GL_DEPTH24_STENCIL8_EXT
;
503 irb
->Base
._BaseFormat
= GL_DEPTH_STENCIL_EXT
;
504 irb
->Base
.DataType
= GL_UNSIGNED_INT_24_8_EXT
;
505 DBG("Render to DEPTH_STENCIL texture OK\n");
508 DBG("Render to texture BAD FORMAT %d\n",
509 texImage
->TexFormat
->MesaFormat
);
513 irb
->Base
.InternalFormat
= irb
->Base
._ActualFormat
;
514 irb
->Base
.Width
= texImage
->Width
;
515 irb
->Base
.Height
= texImage
->Height
;
516 irb
->Base
.RedBits
= texImage
->TexFormat
->RedBits
;
517 irb
->Base
.GreenBits
= texImage
->TexFormat
->GreenBits
;
518 irb
->Base
.BlueBits
= texImage
->TexFormat
->BlueBits
;
519 irb
->Base
.AlphaBits
= texImage
->TexFormat
->AlphaBits
;
520 irb
->Base
.DepthBits
= texImage
->TexFormat
->DepthBits
;
521 irb
->Base
.StencilBits
= texImage
->TexFormat
->StencilBits
;
523 irb
->Base
.Delete
= intel_delete_renderbuffer
;
524 irb
->Base
.AllocStorage
= intel_nop_alloc_storage
;
531 * When glFramebufferTexture[123]D is called this function sets up the
532 * gl_renderbuffer wrapper around the texture image.
533 * This will have the region info needed for hardware rendering.
535 static struct intel_renderbuffer
*
536 intel_wrap_texture(GLcontext
* ctx
, struct gl_texture_image
*texImage
)
538 const GLuint name
= ~0; /* not significant, but distinct for debugging */
539 struct intel_renderbuffer
*irb
;
541 /* make an intel_renderbuffer to wrap the texture image */
542 irb
= CALLOC_STRUCT(intel_renderbuffer
);
544 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glFramebufferTexture");
548 _mesa_init_renderbuffer(&irb
->Base
, name
);
549 irb
->Base
.ClassID
= INTEL_RB_CLASS
;
551 if (!intel_update_wrapper(ctx
, irb
, texImage
)) {
561 * Called by glFramebufferTexture[123]DEXT() (and other places) to
562 * prepare for rendering into texture memory. This might be called
563 * many times to choose different texture levels, cube faces, etc
564 * before intel_finish_render_texture() is ever called.
567 intel_render_texture(GLcontext
* ctx
,
568 struct gl_framebuffer
*fb
,
569 struct gl_renderbuffer_attachment
*att
)
571 struct gl_texture_image
*newImage
572 = att
->Texture
->Image
[att
->CubeMapFace
][att
->TextureLevel
];
573 struct intel_renderbuffer
*irb
= intel_renderbuffer(att
->Renderbuffer
);
574 struct intel_texture_image
*intel_image
;
581 intel_image
= intel_texture_image(newImage
);
582 if (!intel_image
->mt
) {
583 /* Fallback on drawing to a texture that doesn't have a miptree
584 * (has a border, width/height 0, etc.)
586 _mesa_reference_renderbuffer(&att
->Renderbuffer
, NULL
);
587 _mesa_render_texture(ctx
, fb
, att
);
591 irb
= intel_wrap_texture(ctx
, newImage
);
593 /* bind the wrapper to the attachment point */
594 _mesa_reference_renderbuffer(&att
->Renderbuffer
, &irb
->Base
);
597 /* fallback to software rendering */
598 _mesa_render_texture(ctx
, fb
, att
);
603 if (!intel_update_wrapper(ctx
, irb
, newImage
)) {
604 _mesa_reference_renderbuffer(&att
->Renderbuffer
, NULL
);
605 _mesa_render_texture(ctx
, fb
, att
);
609 DBG("Begin render texture tid %x tex=%u w=%d h=%d refcount=%d\n",
611 att
->Texture
->Name
, newImage
->Width
, newImage
->Height
,
614 /* point the renderbufer's region to the texture image region */
615 if (irb
->region
!= intel_image
->mt
->region
) {
617 intel_region_release(&irb
->region
);
618 intel_region_reference(&irb
->region
, intel_image
->mt
->region
);
621 /* compute offset of the particular 2D image within the texture region */
622 intel_miptree_get_image_offset(intel_image
->mt
,
628 intel_image
->mt
->region
->draw_offset
= (dst_y
* intel_image
->mt
->pitch
+
629 dst_x
) * intel_image
->mt
->cpp
;
630 intel_image
->mt
->region
->draw_x
= dst_x
;
631 intel_image
->mt
->region
->draw_y
= dst_y
;
633 /* update drawing region, etc */
634 intel_draw_buffer(ctx
, fb
);
639 * Called by Mesa when rendering to a texture is done.
642 intel_finish_render_texture(GLcontext
* ctx
,
643 struct gl_renderbuffer_attachment
*att
)
646 * Previously we released the renderbuffer's intel_region but
647 * that's not necessary and actually caused problems when trying
648 * to do a glRead/CopyPixels from the renderbuffer later.
649 * The region will be released later if the texture is replaced
650 * or the renderbuffer deleted.
652 * The intention of this driver hook is more of a "done rendering
653 * to texture, please re-twiddle/etc if necessary".
659 * Do additional "completeness" testing of a framebuffer object.
662 intel_validate_framebuffer(GLcontext
*ctx
, struct gl_framebuffer
*fb
)
664 const struct intel_renderbuffer
*depthRb
=
665 intel_get_renderbuffer(fb
, BUFFER_DEPTH
);
666 const struct intel_renderbuffer
*stencilRb
=
667 intel_get_renderbuffer(fb
, BUFFER_STENCIL
);
670 if (stencilRb
&& stencilRb
!= depthRb
) {
671 /* we only support combined depth/stencil buffers, not separate
674 fb
->_Status
= GL_FRAMEBUFFER_UNSUPPORTED_EXT
;
677 for (i
= 0; i
< ctx
->Const
.MaxDrawBuffers
; i
++) {
678 struct gl_renderbuffer
*rb
= ctx
->DrawBuffer
->_ColorDrawBuffers
[i
];
679 struct intel_renderbuffer
*irb
= intel_renderbuffer(rb
);
685 fb
->_Status
= GL_FRAMEBUFFER_UNSUPPORTED_EXT
;
689 switch (irb
->texformat
->MesaFormat
) {
690 case MESA_FORMAT_ARGB8888
:
691 case MESA_FORMAT_RGB565
:
692 case MESA_FORMAT_ARGB1555
:
693 case MESA_FORMAT_ARGB4444
:
696 fb
->_Status
= GL_FRAMEBUFFER_UNSUPPORTED_EXT
;
703 * Do one-time context initializations related to GL_EXT_framebuffer_object.
704 * Hook in device driver functions.
707 intel_fbo_init(struct intel_context
*intel
)
709 intel
->ctx
.Driver
.NewFramebuffer
= intel_new_framebuffer
;
710 intel
->ctx
.Driver
.NewRenderbuffer
= intel_new_renderbuffer
;
711 intel
->ctx
.Driver
.BindFramebuffer
= intel_bind_framebuffer
;
712 intel
->ctx
.Driver
.FramebufferRenderbuffer
= intel_framebuffer_renderbuffer
;
713 intel
->ctx
.Driver
.RenderTexture
= intel_render_texture
;
714 intel
->ctx
.Driver
.FinishRenderTexture
= intel_finish_render_texture
;
715 intel
->ctx
.Driver
.ResizeBuffers
= intel_resize_buffers
;
716 intel
->ctx
.Driver
.ValidateFramebuffer
= intel_validate_framebuffer
;
717 intel
->ctx
.Driver
.BlitFramebuffer
= _mesa_meta_BlitFramebuffer
;