2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2005 Brian Paul All Rights Reserved.
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
39 static struct gl_frame_buffer_object DummyFramebuffer
;
40 static struct gl_render_buffer_object DummyRenderbuffer
;
43 #define IS_CUBE_FACE(TARGET) \
44 ((TARGET) >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && \
45 (TARGET) <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)
49 * Helper routine for getting a gl_render_buffer_object.
51 static struct gl_render_buffer_object
*
52 lookup_renderbuffer(GLcontext
*ctx
, GLuint id
)
54 struct gl_render_buffer_object
*rb
;
59 rb
= (struct gl_render_buffer_object
*)
60 _mesa_HashLookup(ctx
->Shared
->RenderBuffers
, id
);
66 * Helper routine for getting a gl_frame_buffer_object.
68 static struct gl_frame_buffer_object
*
69 lookup_framebuffer(GLcontext
*ctx
, GLuint id
)
71 struct gl_frame_buffer_object
*fb
;
76 fb
= (struct gl_frame_buffer_object
*)
77 _mesa_HashLookup(ctx
->Shared
->FrameBuffers
, id
);
83 * Allocate a new gl_render_buffer_object.
84 * XXX make this a device driver function.
86 static struct gl_render_buffer_object
*
87 new_renderbuffer(GLcontext
*ctx
, GLuint name
)
89 struct gl_render_buffer_object
*rb
= CALLOC_STRUCT(gl_render_buffer_object
);
93 /* other fields are zero */
100 * Allocate a new gl_frame_buffer_object.
101 * XXX make this a device driver function.
103 static struct gl_frame_buffer_object
*
104 new_framebuffer(GLcontext
*ctx
, GLuint name
)
106 struct gl_frame_buffer_object
*fb
= CALLOC_STRUCT(gl_frame_buffer_object
);
115 static struct gl_render_buffer_attachment
*
116 get_attachment(GLcontext
*ctx
, GLenum attachment
)
120 switch (attachment
) {
121 case GL_COLOR_ATTACHMENT0_EXT
:
122 case GL_COLOR_ATTACHMENT1_EXT
:
123 case GL_COLOR_ATTACHMENT2_EXT
:
124 case GL_COLOR_ATTACHMENT3_EXT
:
125 case GL_COLOR_ATTACHMENT4_EXT
:
126 case GL_COLOR_ATTACHMENT5_EXT
:
127 case GL_COLOR_ATTACHMENT6_EXT
:
128 case GL_COLOR_ATTACHMENT7_EXT
:
129 case GL_COLOR_ATTACHMENT8_EXT
:
130 case GL_COLOR_ATTACHMENT9_EXT
:
131 case GL_COLOR_ATTACHMENT10_EXT
:
132 case GL_COLOR_ATTACHMENT11_EXT
:
133 case GL_COLOR_ATTACHMENT12_EXT
:
134 case GL_COLOR_ATTACHMENT13_EXT
:
135 case GL_COLOR_ATTACHMENT14_EXT
:
136 case GL_COLOR_ATTACHMENT15_EXT
:
137 i
= attachment
- GL_COLOR_ATTACHMENT0_EXT
;
138 if (i
>= ctx
->Const
.MaxColorAttachments
) {
141 return &ctx
->CurrentFramebuffer
->ColorAttachment
[i
];
142 case GL_DEPTH_ATTACHMENT_EXT
:
143 return &ctx
->CurrentFramebuffer
->DepthAttachment
;
144 case GL_STENCIL_ATTACHMENT_EXT
:
145 return &ctx
->CurrentFramebuffer
->StencilAttachment
;
153 remove_attachment(GLcontext
*ctx
, struct gl_render_buffer_attachment
*att
)
155 if (att
->Type
== GL_TEXTURE
) {
156 ASSERT(att
->Texture
);
157 ASSERT(!att
->Renderbuffer
);
158 att
->Texture
->RefCount
--;
159 if (att
->Texture
->RefCount
== 0) {
160 ctx
->Driver
.DeleteTexture(ctx
, att
->Texture
);
164 else if (att
->Type
== GL_RENDERBUFFER_EXT
) {
165 ASSERT(att
->Renderbuffer
);
166 ASSERT(!att
->Texture
);
167 att
->Renderbuffer
->RefCount
--;
168 if (att
->Renderbuffer
->RefCount
== 0) {
169 _mesa_free(att
->Renderbuffer
); /* XXX driver free */
171 att
->Renderbuffer
= NULL
;
178 set_texture_attachment(GLcontext
*ctx
,
179 struct gl_render_buffer_attachment
*att
,
180 struct gl_texture_object
*texObj
,
181 GLenum texTarget
, GLuint level
, GLuint zoffset
)
183 remove_attachment(ctx
, att
);
184 att
->Type
= GL_TEXTURE
;
185 att
->Texture
= texObj
;
186 att
->TextureLevel
= level
;
187 if (IS_CUBE_FACE(texTarget
)) {
188 att
->CubeMapFace
= texTarget
- GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
191 att
->CubeMapFace
= 0;
193 att
->Zoffset
= zoffset
;
199 set_renderbuffer_attachment(GLcontext
*ctx
,
200 struct gl_render_buffer_attachment
*att
,
201 struct gl_render_buffer_object
*rb
)
203 remove_attachment(ctx
, att
);
204 att
->Type
= GL_RENDERBUFFER_EXT
;
205 att
->Renderbuffer
= rb
;
211 _mesa_IsRenderbufferEXT(GLuint renderbuffer
)
213 struct gl_render_buffer_object
*rb
;
214 GET_CURRENT_CONTEXT(ctx
);
216 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx
, GL_FALSE
);
218 rb
= lookup_renderbuffer(ctx
, renderbuffer
);
219 return rb
? GL_TRUE
: GL_FALSE
;
224 _mesa_BindRenderbufferEXT(GLenum target
, GLuint renderbuffer
)
226 struct gl_render_buffer_object
*newRb
, *oldRb
;
227 GET_CURRENT_CONTEXT(ctx
);
229 ASSERT_OUTSIDE_BEGIN_END(ctx
);
231 if (target
!= GL_RENDERBUFFER_EXT
) {
232 _mesa_error(ctx
, GL_INVALID_ENUM
,
233 "glBindRenderbufferEXT(target)");
238 newRb
= lookup_renderbuffer(ctx
, renderbuffer
);
239 if (newRb
== &DummyRenderbuffer
) {
240 /* ID was reserved, but no real renderbuffer object made yet */
244 /* create new renderbuffer object */
245 newRb
= new_renderbuffer(ctx
, renderbuffer
);
247 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glBindRenderbufferEXT");
250 _mesa_HashInsert(ctx
->Shared
->RenderBuffers
, renderbuffer
, newRb
);
258 oldRb
= ctx
->CurrentRenderbuffer
;
261 if (oldRb
->RefCount
== 0) {
262 _mesa_free(oldRb
); /* XXX device driver function */
266 ASSERT(newRb
!= &DummyRenderbuffer
);
268 ctx
->CurrentRenderbuffer
= newRb
;
273 _mesa_DeleteRenderbuffersEXT(GLsizei n
, const GLuint
*renderbuffers
)
276 GET_CURRENT_CONTEXT(ctx
);
278 ASSERT_OUTSIDE_BEGIN_END(ctx
);
280 for (i
= 0; i
< n
; i
++) {
281 if (renderbuffers
[i
]) {
282 struct gl_render_buffer_object
*rb
;
283 rb
= lookup_renderbuffer(ctx
, renderbuffers
[i
]);
285 /* remove from hash table immediately, to free the ID */
286 _mesa_HashRemove(ctx
->Shared
->RenderBuffers
, renderbuffers
[i
]);
288 if (rb
!= &DummyRenderbuffer
) {
289 /* But the object will not be freed until it's no longer
290 * bound in any context.
293 if (rb
->RefCount
== 0) {
294 _mesa_free(rb
); /* XXX call device driver function */
304 _mesa_GenRenderbuffersEXT(GLsizei n
, GLuint
*renderbuffers
)
306 GET_CURRENT_CONTEXT(ctx
);
310 ASSERT_OUTSIDE_BEGIN_END(ctx
);
313 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGenRenderbuffersEXT(n)");
320 first
= _mesa_HashFindFreeKeyBlock(ctx
->Shared
->RenderBuffers
, n
);
322 for (i
= 0; i
< n
; i
++) {
323 GLuint name
= first
+ i
;
325 /* insert dummy placeholder into hash table */
326 _glthread_LOCK_MUTEX(ctx
->Shared
->Mutex
);
327 _mesa_HashInsert(ctx
->Shared
->RenderBuffers
, name
, &DummyRenderbuffer
);
328 _glthread_UNLOCK_MUTEX(ctx
->Shared
->Mutex
);
330 renderbuffers
[i
] = name
;
336 base_internal_format(GLcontext
*ctx
, GLenum internalFormat
)
338 switch (internalFormat
) {
345 /*case GL_LUMINANCE:*/
351 /*case GL_LUMINANCE_ALPHA:*/
352 case GL_LUMINANCE4_ALPHA4
:
353 case GL_LUMINANCE6_ALPHA2
:
354 case GL_LUMINANCE8_ALPHA8
:
355 case GL_LUMINANCE12_ALPHA4
:
356 case GL_LUMINANCE12_ALPHA12
:
357 case GL_LUMINANCE16_ALPHA16
:
358 return GL_LUMINANCE_ALPHA
;
359 /*case GL_INTENSITY:*/
383 case GL_STENCIL_INDEX1_EXT
:
384 case GL_STENCIL_INDEX4_EXT
:
385 case GL_STENCIL_INDEX8_EXT
:
386 case GL_STENCIL_INDEX16_EXT
:
387 return GL_STENCIL_INDEX
;
392 if (ctx
->Extensions
.SGIX_depth_texture
) {
393 switch (internalFormat
) {
394 /*case GL_DEPTH_COMPONENT:*/
395 case GL_DEPTH_COMPONENT16_SGIX
:
396 case GL_DEPTH_COMPONENT24_SGIX
:
397 case GL_DEPTH_COMPONENT32_SGIX
:
398 return GL_DEPTH_COMPONENT
;
409 _mesa_RenderbufferStorageEXT(GLenum target
, GLenum internalFormat
,
410 GLsizei width
, GLsizei height
)
413 GET_CURRENT_CONTEXT(ctx
);
415 ASSERT_OUTSIDE_BEGIN_END(ctx
);
417 if (target
!= GL_RENDERBUFFER_EXT
) {
418 _mesa_error(ctx
, GL_INVALID_ENUM
, "glRenderbufferStorageEXT(target)");
422 baseFormat
= base_internal_format(ctx
, internalFormat
);
423 if (baseFormat
== 0) {
424 _mesa_error(ctx
, GL_INVALID_ENUM
,
425 "glRenderbufferStorageEXT(internalFormat)");
429 if (width
< 1 || width
> ctx
->Const
.MaxRenderbufferSize
) {
430 _mesa_error(ctx
, GL_INVALID_VALUE
, "glRenderbufferStorageEXT(width)");
434 if (height
< 1 || height
> ctx
->Const
.MaxRenderbufferSize
) {
435 _mesa_error(ctx
, GL_INVALID_VALUE
, "glRenderbufferStorageEXT(height)");
439 /* XXX this check isn't in the spec, but seems necessary */
440 if (!ctx
->CurrentRenderbuffer
) {
441 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glRenderbufferStorageEXT");
445 if (ctx
->CurrentRenderbuffer
->Data
) {
446 /* XXX device driver free */
447 _mesa_free(ctx
->CurrentRenderbuffer
->Data
);
450 /* XXX device driver allocate, fix size */
451 ctx
->CurrentRenderbuffer
->Data
= _mesa_malloc(width
* height
* 4);
452 if (ctx
->CurrentRenderbuffer
->Data
== NULL
) {
453 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glRenderbufferStorageEXT");
456 ctx
->CurrentRenderbuffer
->InternalFormat
= internalFormat
;
457 ctx
->CurrentRenderbuffer
->Width
= width
;
458 ctx
->CurrentRenderbuffer
->Height
= height
;
463 _mesa_GetRenderbufferParameterivEXT(GLenum target
, GLenum pname
, GLint
*params
)
465 GET_CURRENT_CONTEXT(ctx
);
467 ASSERT_OUTSIDE_BEGIN_END(ctx
);
469 if (target
!= GL_RENDERBUFFER_EXT
) {
470 _mesa_error(ctx
, GL_INVALID_ENUM
,
471 "glGetRenderbufferParameterivEXT(target)");
475 if (!ctx
->CurrentRenderbuffer
) {
476 _mesa_error(ctx
, GL_INVALID_OPERATION
,
477 "glGetRenderbufferParameterivEXT");
482 case GL_RENDERBUFFER_WIDTH_EXT
:
483 *params
= ctx
->CurrentRenderbuffer
->Width
;
485 case GL_RENDERBUFFER_HEIGHT_EXT
:
486 *params
= ctx
->CurrentRenderbuffer
->Height
;
488 case GL_RENDERBUFFER_INTERNAL_FORMAT_EXT
:
489 *params
= ctx
->CurrentRenderbuffer
->InternalFormat
;
492 _mesa_error(ctx
, GL_INVALID_ENUM
,
493 "glGetRenderbufferParameterivEXT(target)");
500 _mesa_IsFramebufferEXT(GLuint framebuffer
)
502 struct gl_frame_buffer_object
*fb
;
503 GET_CURRENT_CONTEXT(ctx
);
505 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx
, GL_FALSE
);
507 fb
= lookup_framebuffer(ctx
, framebuffer
);
508 return fb
? GL_TRUE
: GL_FALSE
;
513 _mesa_BindFramebufferEXT(GLenum target
, GLuint framebuffer
)
515 struct gl_frame_buffer_object
*newFb
, *oldFb
;
516 GET_CURRENT_CONTEXT(ctx
);
518 ASSERT_OUTSIDE_BEGIN_END(ctx
);
520 if (target
!= GL_FRAMEBUFFER_EXT
) {
521 _mesa_error(ctx
, GL_INVALID_ENUM
,
522 "glBindFramebufferEXT(target)");
527 newFb
= lookup_framebuffer(ctx
, framebuffer
);
528 if (newFb
== &DummyFramebuffer
) {
532 /* create new framebuffer object */
533 newFb
= new_framebuffer(ctx
, framebuffer
);
535 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glBindFramebufferEXT");
538 _mesa_HashInsert(ctx
->Shared
->FrameBuffers
, framebuffer
, newFb
);
546 oldFb
= ctx
->CurrentFramebuffer
;
549 if (oldFb
->RefCount
== 0) {
550 _mesa_free(oldFb
); /* XXX device driver function */
554 ASSERT(newFb
!= &DummyFramebuffer
);
556 ctx
->CurrentFramebuffer
= newFb
;
561 _mesa_DeleteFramebuffersEXT(GLsizei n
, const GLuint
*framebuffers
)
564 GET_CURRENT_CONTEXT(ctx
);
566 ASSERT_OUTSIDE_BEGIN_END(ctx
);
568 for (i
= 0; i
< n
; i
++) {
569 if (framebuffers
[i
]) {
570 struct gl_frame_buffer_object
*fb
;
571 fb
= lookup_framebuffer(ctx
, framebuffers
[i
]);
573 /* remove from hash table immediately, to free the ID */
574 _mesa_HashRemove(ctx
->Shared
->FrameBuffers
, framebuffers
[i
]);
576 if (fb
!= &DummyFramebuffer
) {
577 /* But the object will not be freed until it's no longer
578 * bound in any context.
581 if (fb
->RefCount
== 0) {
582 _mesa_free(fb
); /* XXX call device driver function */
592 _mesa_GenFramebuffersEXT(GLsizei n
, GLuint
*framebuffers
)
594 GET_CURRENT_CONTEXT(ctx
);
598 ASSERT_OUTSIDE_BEGIN_END(ctx
);
601 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGenFramebuffersEXT(n)");
608 first
= _mesa_HashFindFreeKeyBlock(ctx
->Shared
->FrameBuffers
, n
);
610 for (i
= 0; i
< n
; i
++) {
611 GLuint name
= first
+ i
;
613 /* insert into hash table */
614 _glthread_LOCK_MUTEX(ctx
->Shared
->Mutex
);
615 _mesa_HashInsert(ctx
->Shared
->FrameBuffers
, name
, &DummyFramebuffer
);
616 _glthread_UNLOCK_MUTEX(ctx
->Shared
->Mutex
);
618 framebuffers
[i
] = name
;
625 _mesa_CheckFramebufferStatusEXT(GLenum target
)
627 GET_CURRENT_CONTEXT(ctx
);
629 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx
, GL_FRAMEBUFFER_STATUS_ERROR_EXT
);
631 if (target
!= GL_FRAMEBUFFER_EXT
) {
632 _mesa_error(ctx
, GL_INVALID_ENUM
,
633 "glCheckFramebufferStatus(target)");
634 return GL_FRAMEBUFFER_STATUS_ERROR_EXT
;
638 GL_FRAMEBUFFER_COMPLETE_EXT
639 GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT
640 GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT
641 GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT
642 GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT
643 GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT
644 GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT
645 GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT
646 GL_FRAMEBUFFER_UNSUPPORTED_EXT
647 GL_FRAMEBUFFER_STATUS_ERROR_EXT
649 return GL_FRAMEBUFFER_STATUS_ERROR_EXT
;
655 * Do error checking common to glFramebufferTexture1D/2D/3DEXT.
656 * \return GL_TRUE if any error, GL_FALSE otherwise
659 error_check_framebuffer_texture(GLcontext
*ctx
, GLuint dims
,
660 GLenum target
, GLenum attachment
,
661 GLenum textarget
, GLuint texture
, GLint level
)
663 ASSERT(dims
>= 1 && dims
<= 3);
665 if (target
!= GL_FRAMEBUFFER_EXT
) {
666 _mesa_error(ctx
, GL_INVALID_ENUM
,
667 "glFramebufferTexture%dDEXT(target)", dims
);
671 if (ctx
->CurrentFramebuffer
== NULL
) {
672 _mesa_error(ctx
, GL_INVALID_OPERATION
,
673 "glFramebufferTexture%dDEXT", dims
);
677 /* only check textarget, level if texture ID is non-zero*/
679 if ((dims
== 1 && textarget
!= GL_TEXTURE_1D
) ||
680 (dims
== 3 && textarget
!= GL_TEXTURE_3D
) ||
681 (dims
== 2 && textarget
!= GL_TEXTURE_2D
&&
682 textarget
!= GL_TEXTURE_RECTANGLE_ARB
&&
683 !IS_CUBE_FACE(textarget
))) {
684 _mesa_error(ctx
, GL_INVALID_VALUE
,
685 "glFramebufferTexture%dDEXT(textarget)", dims
);
689 if ((level
< 0) || level
>= _mesa_max_texture_levels(ctx
, textarget
)) {
690 _mesa_error(ctx
, GL_INVALID_VALUE
,
691 "glFramebufferTexture%dDEXT(level)", dims
);
701 _mesa_FramebufferTexture1DEXT(GLenum target
, GLenum attachment
,
702 GLenum textarget
, GLuint texture
, GLint level
)
704 struct gl_render_buffer_attachment
*att
;
705 GET_CURRENT_CONTEXT(ctx
);
707 ASSERT_OUTSIDE_BEGIN_END(ctx
);
709 if (error_check_framebuffer_texture(ctx
, 1, target
, attachment
,
710 textarget
, texture
, level
))
713 ASSERT(textarget
== GL_TEXTURE_1D
);
715 att
= get_attachment(ctx
, attachment
);
717 _mesa_error(ctx
, GL_INVALID_ENUM
,
718 "glFramebufferTexture1DEXT(attachment)");
723 struct gl_texture_object
*texObj
= (struct gl_texture_object
*)
724 _mesa_HashLookup(ctx
->Shared
->TexObjects
, texture
);
726 _mesa_error(ctx
, GL_INVALID_VALUE
,
727 "glFramebufferTexture1DEXT(texture)");
730 if (texObj
->Target
!= textarget
) {
731 _mesa_error(ctx
, GL_INVALID_OPERATION
, /* XXX correct error? */
732 "glFramebufferTexture1DEXT(texture target)");
735 set_texture_attachment(ctx
, att
, texObj
, textarget
, level
, 0);
738 remove_attachment(ctx
, att
);
741 /* XXX call a driver function to signal new attachment? */
746 _mesa_FramebufferTexture2DEXT(GLenum target
, GLenum attachment
,
747 GLenum textarget
, GLuint texture
, GLint level
)
749 struct gl_render_buffer_attachment
*att
;
750 GET_CURRENT_CONTEXT(ctx
);
752 ASSERT_OUTSIDE_BEGIN_END(ctx
);
754 if (error_check_framebuffer_texture(ctx
, 2, target
, attachment
,
755 textarget
, texture
, level
))
758 ASSERT(textarget
== GL_TEXTURE_2D
||
759 textarget
== GL_TEXTURE_RECTANGLE_ARB
||
760 IS_CUBE_FACE(textarget
));
762 att
= get_attachment(ctx
, attachment
);
764 _mesa_error(ctx
, GL_INVALID_ENUM
,
765 "glFramebufferTexture2DEXT(attachment)");
770 struct gl_texture_object
*texObj
= (struct gl_texture_object
*)
771 _mesa_HashLookup(ctx
->Shared
->TexObjects
, texture
);
773 _mesa_error(ctx
, GL_INVALID_VALUE
,
774 "glFramebufferTexture2DEXT(texture)");
777 if ((texObj
->Target
== GL_TEXTURE_2D
&& textarget
!= GL_TEXTURE_2D
) ||
778 (texObj
->Target
== GL_TEXTURE_RECTANGLE_ARB
779 && textarget
!= GL_TEXTURE_RECTANGLE_ARB
) ||
780 (texObj
->Target
== GL_TEXTURE_CUBE_MAP
781 && !IS_CUBE_FACE(textarget
))) {
782 _mesa_error(ctx
, GL_INVALID_OPERATION
, /* XXX correct error? */
783 "glFramebufferTexture2DEXT(texture target)");
786 set_texture_attachment(ctx
, att
, texObj
, textarget
, level
, 0);
789 remove_attachment(ctx
, att
);
796 _mesa_FramebufferTexture3DEXT(GLenum target
, GLenum attachment
,
797 GLenum textarget
, GLuint texture
,
798 GLint level
, GLint zoffset
)
800 struct gl_render_buffer_attachment
*att
;
801 GET_CURRENT_CONTEXT(ctx
);
803 ASSERT_OUTSIDE_BEGIN_END(ctx
);
805 if (error_check_framebuffer_texture(ctx
, 3, target
, attachment
,
806 textarget
, texture
, level
))
809 ASSERT(textarget
== GL_TEXTURE_3D
);
811 att
= get_attachment(ctx
, attachment
);
813 _mesa_error(ctx
, GL_INVALID_ENUM
,
814 "glFramebufferTexture1DEXT(attachment)");
819 struct gl_texture_object
*texObj
= (struct gl_texture_object
*)
820 _mesa_HashLookup(ctx
->Shared
->TexObjects
, texture
);
822 _mesa_error(ctx
, GL_INVALID_VALUE
,
823 "glFramebufferTexture3DEXT(texture)");
826 if (texObj
->Target
!= textarget
) {
827 _mesa_error(ctx
, GL_INVALID_OPERATION
, /* XXX correct error? */
828 "glFramebufferTexture3DEXT(texture target)");
831 if (zoffset
>= texObj
->Image
[0][level
]->Depth
) {
832 _mesa_error(ctx
, GL_INVALID_VALUE
,
833 "glFramebufferTexture3DEXT(zoffset)");
836 set_texture_attachment(ctx
, att
, texObj
, textarget
, level
, zoffset
);
839 remove_attachment(ctx
, att
);
845 _mesa_FramebufferRenderbufferEXT(GLenum target
, GLenum attachment
,
846 GLenum renderbufferTarget
,
849 struct gl_render_buffer_attachment
*att
;
850 GET_CURRENT_CONTEXT(ctx
);
852 ASSERT_OUTSIDE_BEGIN_END(ctx
);
854 if (target
!= GL_FRAMEBUFFER_EXT
) {
855 _mesa_error(ctx
, GL_INVALID_ENUM
,
856 "glFramebufferRenderbufferEXT(target)");
860 if (renderbufferTarget
!= GL_RENDERBUFFER_EXT
) {
861 _mesa_error(ctx
, GL_INVALID_ENUM
,
862 "glFramebufferRenderbufferEXT(renderbufferTarget)");
866 if (ctx
->CurrentFramebuffer
== NULL
) {
867 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glFramebufferRenderbufferEXT");
871 att
= get_attachment(ctx
, attachment
);
873 _mesa_error(ctx
, GL_INVALID_ENUM
,
874 "glFramebufferRenderbufferEXT(attachment)");
879 struct gl_render_buffer_object
*rb
;
880 rb
= lookup_renderbuffer(ctx
, renderbuffer
);
882 _mesa_error(ctx
, GL_INVALID_VALUE
,
883 "glFramebufferRenderbufferEXT(renderbuffer)");
886 set_renderbuffer_attachment(ctx
, att
, rb
);
889 remove_attachment(ctx
, att
);
895 _mesa_GetFramebufferAttachmentParameterivEXT(GLenum target
, GLenum attachment
,
896 GLenum pname
, GLint
*params
)
898 const struct gl_render_buffer_attachment
*att
;
899 GET_CURRENT_CONTEXT(ctx
);
901 ASSERT_OUTSIDE_BEGIN_END(ctx
);
903 if (target
!= GL_FRAMEBUFFER_EXT
) {
904 _mesa_error(ctx
, GL_INVALID_ENUM
,
905 "glGetFramebufferAttachmentParameterivEXT(target)");
909 if (ctx
->CurrentFramebuffer
== NULL
) {
910 _mesa_error(ctx
, GL_INVALID_OPERATION
,
911 "glGetFramebufferAttachmentParameterivEXT");
915 att
= get_attachment(ctx
, attachment
);
917 _mesa_error(ctx
, GL_INVALID_ENUM
,
918 "glGetFramebufferAttachmentParameterivEXT(attachment)");
923 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT
:
926 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT
:
927 if (att
->Type
== GL_RENDERBUFFER_EXT
) {
928 *params
= att
->Renderbuffer
->Name
;
930 else if (att
->Type
== GL_TEXTURE
) {
931 *params
= att
->Texture
->Name
;
934 _mesa_error(ctx
, GL_INVALID_ENUM
,
935 "glGetFramebufferAttachmentParameterivEXT(pname)");
938 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT
:
939 if (att
->Type
== GL_TEXTURE
) {
940 *params
= att
->TextureLevel
;
943 _mesa_error(ctx
, GL_INVALID_ENUM
,
944 "glGetFramebufferAttachmentParameterivEXT(pname)");
947 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT
:
948 if (att
->Type
== GL_TEXTURE
) {
949 *params
= GL_TEXTURE_CUBE_MAP_POSITIVE_X
+ att
->CubeMapFace
;
952 _mesa_error(ctx
, GL_INVALID_ENUM
,
953 "glGetFramebufferAttachmentParameterivEXT(pname)");
956 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT
:
957 if (att
->Type
== GL_TEXTURE
) {
958 *params
= att
->Zoffset
;
961 _mesa_error(ctx
, GL_INVALID_ENUM
,
962 "glGetFramebufferAttachmentParameterivEXT(pname)");
966 _mesa_error(ctx
, GL_INVALID_ENUM
,
967 "glGetFramebufferAttachmentParameterivEXT(pname)");
974 _mesa_GenerateMipmapEXT(GLenum target
)
976 struct gl_texture_unit
*texUnit
;
977 struct gl_texture_object
*texObj
;
978 GET_CURRENT_CONTEXT(ctx
);
980 ASSERT_OUTSIDE_BEGIN_END(ctx
);
986 case GL_TEXTURE_CUBE_MAP
:
989 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGenerateMipmapEXT(target)");
993 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
994 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
996 /* XXX this might not handle cube maps correctly */
997 _mesa_generate_mipmap(ctx
, target
, texUnit
, texObj
);