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/texrender.h"
37 #include "drivers/common/meta.h"
39 #include "intel_context.h"
40 #include "intel_buffers.h"
41 #include "intel_fbo.h"
42 #include "intel_mipmap_tree.h"
43 #include "intel_regions.h"
46 #define FILE_DEBUG_FLAG DEBUG_FBO
50 * Create a new framebuffer object.
52 static struct gl_framebuffer
*
53 intel_new_framebuffer(GLcontext
* ctx
, GLuint name
)
55 /* Only drawable state in intel_framebuffer at this time, just use Mesa's
58 return _mesa_new_framebuffer(ctx
, name
);
62 /** Called by gl_renderbuffer::Delete() */
64 intel_delete_renderbuffer(struct gl_renderbuffer
*rb
)
66 GET_CURRENT_CONTEXT(ctx
);
67 struct intel_context
*intel
= intel_context(ctx
);
68 struct intel_renderbuffer
*irb
= intel_renderbuffer(rb
);
72 if (irb
->span_cache
!= NULL
)
73 _mesa_free(irb
->span_cache
);
75 if (intel
&& irb
->region
) {
76 intel_region_release(&irb
->region
);
84 * Return a pointer to a specific pixel in a renderbuffer.
87 intel_get_pointer(GLcontext
* ctx
, struct gl_renderbuffer
*rb
,
90 /* By returning NULL we force all software rendering to go through
98 * Called via glRenderbufferStorageEXT() to set the format and allocate
99 * storage for a user-created renderbuffer.
102 intel_alloc_renderbuffer_storage(GLcontext
* ctx
, struct gl_renderbuffer
*rb
,
103 GLenum internalFormat
,
104 GLuint width
, GLuint height
)
106 struct intel_context
*intel
= intel_context(ctx
);
107 struct intel_renderbuffer
*irb
= intel_renderbuffer(rb
);
108 GLboolean softwareBuffer
= GL_FALSE
;
111 ASSERT(rb
->Name
!= 0);
113 switch (internalFormat
) {
117 rb
->Format
= MESA_FORMAT_RGB565
;
118 rb
->DataType
= GL_UNSIGNED_BYTE
;
119 irb
->texformat
= MESA_FORMAT_RGB565
;
127 rb
->Format
= MESA_FORMAT_ARGB8888
;
128 rb
->DataType
= GL_UNSIGNED_BYTE
;
129 irb
->texformat
= MESA_FORMAT_XRGB8888
;
140 rb
->Format
= MESA_FORMAT_ARGB8888
;
141 rb
->DataType
= GL_UNSIGNED_BYTE
;
142 irb
->texformat
= MESA_FORMAT_ARGB8888
;
145 case GL_STENCIL_INDEX
:
146 case GL_STENCIL_INDEX1_EXT
:
147 case GL_STENCIL_INDEX4_EXT
:
148 case GL_STENCIL_INDEX8_EXT
:
149 case GL_STENCIL_INDEX16_EXT
:
150 /* alloc a depth+stencil buffer */
151 rb
->Format
= MESA_FORMAT_S8_Z24
;
152 rb
->DataType
= GL_UNSIGNED_INT_24_8_EXT
;
154 irb
->texformat
= MESA_FORMAT_S8_Z24
;
156 case GL_DEPTH_COMPONENT16
:
157 rb
->Format
= MESA_FORMAT_Z16
;
158 rb
->DataType
= GL_UNSIGNED_SHORT
;
160 irb
->texformat
= MESA_FORMAT_Z16
;
162 case GL_DEPTH_COMPONENT
:
163 case GL_DEPTH_COMPONENT24
:
164 case GL_DEPTH_COMPONENT32
:
165 rb
->Format
= MESA_FORMAT_S8_Z24
;
166 rb
->DataType
= GL_UNSIGNED_INT_24_8_EXT
;
168 irb
->texformat
= MESA_FORMAT_S8_Z24
;
170 case GL_DEPTH_STENCIL_EXT
:
171 case GL_DEPTH24_STENCIL8_EXT
:
172 rb
->Format
= MESA_FORMAT_S8_Z24
;
173 rb
->DataType
= GL_UNSIGNED_INT_24_8_EXT
;
175 irb
->texformat
= MESA_FORMAT_S8_Z24
;
179 "Unexpected format in intel_alloc_renderbuffer_storage");
183 rb
->_BaseFormat
= _mesa_base_fbo_format(ctx
, internalFormat
);
187 /* free old region */
189 intel_region_release(&irb
->region
);
192 /* allocate new memory region/renderbuffer */
193 if (softwareBuffer
) {
194 return _mesa_soft_renderbuffer_storage(ctx
, rb
, internalFormat
,
198 /* Choose a pitch to match hardware requirements:
200 GLuint pitch
= ((cpp
* width
+ 63) & ~63) / cpp
;
202 /* alloc hardware renderbuffer */
203 DBG("Allocating %d x %d Intel RBO (pitch %d)\n", width
,
206 irb
->region
= intel_region_alloc(intel
, I915_TILING_NONE
,
207 cpp
, width
, height
, pitch
,
210 return GL_FALSE
; /* out of memory? */
212 ASSERT(irb
->region
->buffer
);
223 * Called for each hardware renderbuffer when a _window_ is resized.
224 * Just update fields.
225 * Not used for user-created renderbuffers!
228 intel_alloc_window_storage(GLcontext
* ctx
, struct gl_renderbuffer
*rb
,
229 GLenum internalFormat
, GLuint width
, GLuint height
)
231 ASSERT(rb
->Name
== 0);
234 rb
->InternalFormat
= internalFormat
;
241 intel_resize_buffers(GLcontext
*ctx
, struct gl_framebuffer
*fb
,
242 GLuint width
, GLuint height
)
244 struct intel_framebuffer
*intel_fb
= (struct intel_framebuffer
*)fb
;
247 _mesa_resize_framebuffer(ctx
, fb
, width
, height
);
249 fb
->Initialized
= GL_TRUE
; /* XXX remove someday */
255 /* Make sure all window system renderbuffers are up to date */
256 for (i
= 0; i
< 2; i
++) {
257 struct gl_renderbuffer
*rb
= &intel_fb
->color_rb
[i
]->Base
;
259 /* only resize if size is changing */
260 if (rb
&& (rb
->Width
!= width
|| rb
->Height
!= height
)) {
261 rb
->AllocStorage(ctx
, rb
, rb
->InternalFormat
, width
, height
);
267 /** Dummy function for gl_renderbuffer::AllocStorage() */
269 intel_nop_alloc_storage(GLcontext
* ctx
, struct gl_renderbuffer
*rb
,
270 GLenum internalFormat
, GLuint width
, GLuint height
)
272 _mesa_problem(ctx
, "intel_op_alloc_storage should never be called.");
278 intel_renderbuffer_set_region(struct intel_renderbuffer
*rb
,
279 struct intel_region
*region
)
281 struct intel_region
*old
;
285 intel_region_reference(&rb
->region
, region
);
286 intel_region_release(&old
);
291 * Create a new intel_renderbuffer which corresponds to an on-screen window,
292 * not a user-created renderbuffer.
294 struct intel_renderbuffer
*
295 intel_create_renderbuffer(gl_format format
)
297 GET_CURRENT_CONTEXT(ctx
);
299 struct intel_renderbuffer
*irb
;
300 const GLuint name
= 0;
302 irb
= CALLOC_STRUCT(intel_renderbuffer
);
304 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "creating renderbuffer");
308 _mesa_init_renderbuffer(&irb
->Base
, name
);
309 irb
->Base
.ClassID
= INTEL_RB_CLASS
;
312 case MESA_FORMAT_RGB565
:
313 irb
->Base
._BaseFormat
= GL_RGB
;
314 irb
->Base
.DataType
= GL_UNSIGNED_BYTE
;
316 case MESA_FORMAT_XRGB8888
:
317 irb
->Base
._BaseFormat
= GL_RGB
;
318 irb
->Base
.DataType
= GL_UNSIGNED_BYTE
;
320 case MESA_FORMAT_ARGB8888
:
321 irb
->Base
._BaseFormat
= GL_RGBA
;
322 irb
->Base
.DataType
= GL_UNSIGNED_BYTE
;
324 case MESA_FORMAT_Z16
:
325 irb
->Base
._BaseFormat
= GL_DEPTH_COMPONENT
;
326 irb
->Base
.DataType
= GL_UNSIGNED_SHORT
;
328 case MESA_FORMAT_X8_Z24
:
329 irb
->Base
._BaseFormat
= GL_DEPTH_COMPONENT
;
330 irb
->Base
.DataType
= GL_UNSIGNED_INT
;
332 case MESA_FORMAT_S8_Z24
:
333 irb
->Base
._BaseFormat
= GL_DEPTH_STENCIL
;
334 irb
->Base
.DataType
= GL_UNSIGNED_INT_24_8_EXT
;
338 "Unexpected intFormat in intel_create_renderbuffer");
343 irb
->Base
.Format
= format
;
344 irb
->Base
.InternalFormat
= irb
->Base
._BaseFormat
;
345 irb
->texformat
= format
;
347 /* intel-specific methods */
348 irb
->Base
.Delete
= intel_delete_renderbuffer
;
349 irb
->Base
.AllocStorage
= intel_alloc_window_storage
;
350 irb
->Base
.GetPointer
= intel_get_pointer
;
357 * Create a new renderbuffer object.
358 * Typically called via glBindRenderbufferEXT().
360 static struct gl_renderbuffer
*
361 intel_new_renderbuffer(GLcontext
* ctx
, GLuint name
)
363 /*struct intel_context *intel = intel_context(ctx); */
364 struct intel_renderbuffer
*irb
;
366 irb
= CALLOC_STRUCT(intel_renderbuffer
);
368 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "creating renderbuffer");
372 _mesa_init_renderbuffer(&irb
->Base
, name
);
373 irb
->Base
.ClassID
= INTEL_RB_CLASS
;
375 /* intel-specific methods */
376 irb
->Base
.Delete
= intel_delete_renderbuffer
;
377 irb
->Base
.AllocStorage
= intel_alloc_renderbuffer_storage
;
378 irb
->Base
.GetPointer
= intel_get_pointer
;
379 /* span routines set in alloc_storage function */
386 * Called via glBindFramebufferEXT().
389 intel_bind_framebuffer(GLcontext
* ctx
, GLenum target
,
390 struct gl_framebuffer
*fb
, struct gl_framebuffer
*fbread
)
392 if (target
== GL_FRAMEBUFFER_EXT
|| target
== GL_DRAW_FRAMEBUFFER_EXT
) {
393 intel_draw_buffer(ctx
, fb
);
396 /* don't need to do anything if target == GL_READ_FRAMEBUFFER_EXT */
402 * Called via glFramebufferRenderbufferEXT().
405 intel_framebuffer_renderbuffer(GLcontext
* ctx
,
406 struct gl_framebuffer
*fb
,
407 GLenum attachment
, struct gl_renderbuffer
*rb
)
409 DBG("Intel FramebufferRenderbuffer %u %u\n", fb
->Name
, rb
? rb
->Name
: 0);
413 _mesa_framebuffer_renderbuffer(ctx
, fb
, attachment
, rb
);
414 intel_draw_buffer(ctx
, fb
);
419 intel_update_wrapper(GLcontext
*ctx
, struct intel_renderbuffer
*irb
,
420 struct gl_texture_image
*texImage
)
422 irb
->texformat
= texImage
->TexFormat
;
425 if (texImage
->TexFormat
== MESA_FORMAT_ARGB8888
) {
426 irb
->Base
.DataType
= GL_UNSIGNED_BYTE
;
427 DBG("Render to RGBA8 texture OK\n");
429 else if (texImage
->TexFormat
== MESA_FORMAT_XRGB8888
) {
430 irb
->Base
.DataType
= GL_UNSIGNED_BYTE
;
431 DBG("Render to XGBA8 texture OK\n");
433 else if (texImage
->TexFormat
== MESA_FORMAT_RGB565
) {
434 irb
->Base
.DataType
= GL_UNSIGNED_BYTE
;
435 DBG("Render to RGB5 texture OK\n");
437 else if (texImage
->TexFormat
== MESA_FORMAT_ARGB1555
) {
438 irb
->Base
.DataType
= GL_UNSIGNED_BYTE
;
439 DBG("Render to ARGB1555 texture OK\n");
441 else if (texImage
->TexFormat
== MESA_FORMAT_ARGB4444
) {
442 irb
->Base
.DataType
= GL_UNSIGNED_BYTE
;
443 DBG("Render to ARGB4444 texture OK\n");
445 else if (texImage
->TexFormat
== MESA_FORMAT_Z16
) {
446 irb
->Base
.DataType
= GL_UNSIGNED_SHORT
;
447 DBG("Render to DEPTH16 texture OK\n");
449 else if (texImage
->TexFormat
== MESA_FORMAT_S8_Z24
) {
450 irb
->Base
.DataType
= GL_UNSIGNED_INT_24_8_EXT
;
451 DBG("Render to DEPTH_STENCIL texture OK\n");
454 DBG("Render to texture BAD FORMAT %d\n", texImage
->TexFormat
);
458 irb
->Base
.Format
= texImage
->TexFormat
;
460 texFormat
= texImage
->TexFormat
;
462 irb
->Base
.InternalFormat
= texImage
->InternalFormat
;
463 irb
->Base
._BaseFormat
= _mesa_base_fbo_format(ctx
, irb
->Base
.InternalFormat
);
464 irb
->Base
.Width
= texImage
->Width
;
465 irb
->Base
.Height
= texImage
->Height
;
467 irb
->Base
.Delete
= intel_delete_renderbuffer
;
468 irb
->Base
.AllocStorage
= intel_nop_alloc_storage
;
475 * When glFramebufferTexture[123]D is called this function sets up the
476 * gl_renderbuffer wrapper around the texture image.
477 * This will have the region info needed for hardware rendering.
479 static struct intel_renderbuffer
*
480 intel_wrap_texture(GLcontext
* ctx
, struct gl_texture_image
*texImage
)
482 const GLuint name
= ~0; /* not significant, but distinct for debugging */
483 struct intel_renderbuffer
*irb
;
485 /* make an intel_renderbuffer to wrap the texture image */
486 irb
= CALLOC_STRUCT(intel_renderbuffer
);
488 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glFramebufferTexture");
492 _mesa_init_renderbuffer(&irb
->Base
, name
);
493 irb
->Base
.ClassID
= INTEL_RB_CLASS
;
495 if (!intel_update_wrapper(ctx
, irb
, texImage
)) {
505 * Called by glFramebufferTexture[123]DEXT() (and other places) to
506 * prepare for rendering into texture memory. This might be called
507 * many times to choose different texture levels, cube faces, etc
508 * before intel_finish_render_texture() is ever called.
511 intel_render_texture(GLcontext
* ctx
,
512 struct gl_framebuffer
*fb
,
513 struct gl_renderbuffer_attachment
*att
)
515 struct gl_texture_image
*newImage
516 = att
->Texture
->Image
[att
->CubeMapFace
][att
->TextureLevel
];
517 struct intel_renderbuffer
*irb
= intel_renderbuffer(att
->Renderbuffer
);
518 struct intel_texture_image
*intel_image
;
525 intel_image
= intel_texture_image(newImage
);
526 if (!intel_image
->mt
) {
527 /* Fallback on drawing to a texture that doesn't have a miptree
528 * (has a border, width/height 0, etc.)
530 _mesa_reference_renderbuffer(&att
->Renderbuffer
, NULL
);
531 _mesa_render_texture(ctx
, fb
, att
);
535 irb
= intel_wrap_texture(ctx
, newImage
);
537 /* bind the wrapper to the attachment point */
538 _mesa_reference_renderbuffer(&att
->Renderbuffer
, &irb
->Base
);
541 /* fallback to software rendering */
542 _mesa_render_texture(ctx
, fb
, att
);
547 if (!intel_update_wrapper(ctx
, irb
, newImage
)) {
548 _mesa_reference_renderbuffer(&att
->Renderbuffer
, NULL
);
549 _mesa_render_texture(ctx
, fb
, att
);
553 DBG("Begin render texture tid %x tex=%u w=%d h=%d refcount=%d\n",
555 att
->Texture
->Name
, newImage
->Width
, newImage
->Height
,
558 /* point the renderbufer's region to the texture image region */
559 if (irb
->region
!= intel_image
->mt
->region
) {
561 intel_region_release(&irb
->region
);
562 intel_region_reference(&irb
->region
, intel_image
->mt
->region
);
565 /* compute offset of the particular 2D image within the texture region */
566 intel_miptree_get_image_offset(intel_image
->mt
,
572 intel_image
->mt
->region
->draw_offset
= (dst_y
* intel_image
->mt
->pitch
+
573 dst_x
) * intel_image
->mt
->cpp
;
574 intel_image
->mt
->region
->draw_x
= dst_x
;
575 intel_image
->mt
->region
->draw_y
= dst_y
;
576 intel_image
->used_as_render_target
= GL_TRUE
;
578 /* update drawing region, etc */
579 intel_draw_buffer(ctx
, fb
);
584 * Called by Mesa when rendering to a texture is done.
587 intel_finish_render_texture(GLcontext
* ctx
,
588 struct gl_renderbuffer_attachment
*att
)
590 struct gl_texture_object
*tex_obj
= att
->Texture
;
591 struct gl_texture_image
*image
=
592 tex_obj
->Image
[att
->CubeMapFace
][att
->TextureLevel
];
593 struct intel_texture_image
*intel_image
= intel_texture_image(image
);
595 /* Flag that this image may now be validated into the object's miptree. */
596 intel_image
->used_as_render_target
= GL_FALSE
;
601 * Do additional "completeness" testing of a framebuffer object.
604 intel_validate_framebuffer(GLcontext
*ctx
, struct gl_framebuffer
*fb
)
606 const struct intel_renderbuffer
*depthRb
=
607 intel_get_renderbuffer(fb
, BUFFER_DEPTH
);
608 const struct intel_renderbuffer
*stencilRb
=
609 intel_get_renderbuffer(fb
, BUFFER_STENCIL
);
612 if (stencilRb
&& stencilRb
!= depthRb
) {
613 /* we only support combined depth/stencil buffers, not separate
616 fb
->_Status
= GL_FRAMEBUFFER_UNSUPPORTED_EXT
;
619 for (i
= 0; i
< ctx
->Const
.MaxDrawBuffers
; i
++) {
620 struct gl_renderbuffer
*rb
= ctx
->DrawBuffer
->_ColorDrawBuffers
[i
];
621 struct intel_renderbuffer
*irb
= intel_renderbuffer(rb
);
627 fb
->_Status
= GL_FRAMEBUFFER_UNSUPPORTED_EXT
;
631 switch (irb
->texformat
) {
632 case MESA_FORMAT_ARGB8888
:
633 case MESA_FORMAT_XRGB8888
:
634 case MESA_FORMAT_RGB565
:
635 case MESA_FORMAT_ARGB1555
:
636 case MESA_FORMAT_ARGB4444
:
639 fb
->_Status
= GL_FRAMEBUFFER_UNSUPPORTED_EXT
;
646 * Do one-time context initializations related to GL_EXT_framebuffer_object.
647 * Hook in device driver functions.
650 intel_fbo_init(struct intel_context
*intel
)
652 intel
->ctx
.Driver
.NewFramebuffer
= intel_new_framebuffer
;
653 intel
->ctx
.Driver
.NewRenderbuffer
= intel_new_renderbuffer
;
654 intel
->ctx
.Driver
.BindFramebuffer
= intel_bind_framebuffer
;
655 intel
->ctx
.Driver
.FramebufferRenderbuffer
= intel_framebuffer_renderbuffer
;
656 intel
->ctx
.Driver
.RenderTexture
= intel_render_texture
;
657 intel
->ctx
.Driver
.FinishRenderTexture
= intel_finish_render_texture
;
658 intel
->ctx
.Driver
.ResizeBuffers
= intel_resize_buffers
;
659 intel
->ctx
.Driver
.ValidateFramebuffer
= intel_validate_framebuffer
;
660 intel
->ctx
.Driver
.BlitFramebuffer
= _mesa_meta_BlitFramebuffer
;