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.
40 * When glGenRender/FramebuffersEXT() is called we insert pointers to
41 * these placeholder objects into the hash table.
42 * Later, when the object ID is first bound, we replace the placeholder
43 * with the real frame/renderbuffer.
45 static struct gl_frame_buffer_object DummyFramebuffer
;
46 static struct gl_render_buffer_object DummyRenderbuffer
;
49 #define IS_CUBE_FACE(TARGET) \
50 ((TARGET) >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && \
51 (TARGET) <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)
55 * Helper routine for getting a gl_render_buffer_object.
57 static struct gl_render_buffer_object
*
58 lookup_renderbuffer(GLcontext
*ctx
, GLuint id
)
60 struct gl_render_buffer_object
*rb
;
65 rb
= (struct gl_render_buffer_object
*)
66 _mesa_HashLookup(ctx
->Shared
->RenderBuffers
, id
);
72 * Helper routine for getting a gl_frame_buffer_object.
74 static struct gl_frame_buffer_object
*
75 lookup_framebuffer(GLcontext
*ctx
, GLuint id
)
77 struct gl_frame_buffer_object
*fb
;
82 fb
= (struct gl_frame_buffer_object
*)
83 _mesa_HashLookup(ctx
->Shared
->FrameBuffers
, id
);
89 * Allocate a new gl_render_buffer_object.
90 * XXX make this a device driver function.
92 static struct gl_render_buffer_object
*
93 new_renderbuffer(GLcontext
*ctx
, GLuint name
)
95 struct gl_render_buffer_object
*rb
= CALLOC_STRUCT(gl_render_buffer_object
);
99 /* other fields are zero */
106 * Allocate a new gl_frame_buffer_object.
107 * XXX make this a device driver function.
109 static struct gl_frame_buffer_object
*
110 new_framebuffer(GLcontext
*ctx
, GLuint name
)
112 struct gl_frame_buffer_object
*fb
= CALLOC_STRUCT(gl_frame_buffer_object
);
121 static struct gl_render_buffer_attachment
*
122 get_attachment(GLcontext
*ctx
, GLenum attachment
)
126 switch (attachment
) {
127 case GL_COLOR_ATTACHMENT0_EXT
:
128 case GL_COLOR_ATTACHMENT1_EXT
:
129 case GL_COLOR_ATTACHMENT2_EXT
:
130 case GL_COLOR_ATTACHMENT3_EXT
:
131 case GL_COLOR_ATTACHMENT4_EXT
:
132 case GL_COLOR_ATTACHMENT5_EXT
:
133 case GL_COLOR_ATTACHMENT6_EXT
:
134 case GL_COLOR_ATTACHMENT7_EXT
:
135 case GL_COLOR_ATTACHMENT8_EXT
:
136 case GL_COLOR_ATTACHMENT9_EXT
:
137 case GL_COLOR_ATTACHMENT10_EXT
:
138 case GL_COLOR_ATTACHMENT11_EXT
:
139 case GL_COLOR_ATTACHMENT12_EXT
:
140 case GL_COLOR_ATTACHMENT13_EXT
:
141 case GL_COLOR_ATTACHMENT14_EXT
:
142 case GL_COLOR_ATTACHMENT15_EXT
:
143 i
= attachment
- GL_COLOR_ATTACHMENT0_EXT
;
144 if (i
>= ctx
->Const
.MaxColorAttachments
) {
147 return &ctx
->CurrentFramebuffer
->ColorAttachment
[i
];
148 case GL_DEPTH_ATTACHMENT_EXT
:
149 return &ctx
->CurrentFramebuffer
->DepthAttachment
;
150 case GL_STENCIL_ATTACHMENT_EXT
:
151 return &ctx
->CurrentFramebuffer
->StencilAttachment
;
159 remove_attachment(GLcontext
*ctx
, struct gl_render_buffer_attachment
*att
)
161 if (att
->Type
== GL_TEXTURE
) {
162 ASSERT(att
->Texture
);
163 ASSERT(!att
->Renderbuffer
);
164 att
->Texture
->RefCount
--;
165 if (att
->Texture
->RefCount
== 0) {
166 ctx
->Driver
.DeleteTexture(ctx
, att
->Texture
);
170 else if (att
->Type
== GL_RENDERBUFFER_EXT
) {
171 ASSERT(att
->Renderbuffer
);
172 ASSERT(!att
->Texture
);
173 att
->Renderbuffer
->RefCount
--;
174 if (att
->Renderbuffer
->RefCount
== 0) {
175 _mesa_free(att
->Renderbuffer
); /* XXX driver free */
177 att
->Renderbuffer
= NULL
;
184 set_texture_attachment(GLcontext
*ctx
,
185 struct gl_render_buffer_attachment
*att
,
186 struct gl_texture_object
*texObj
,
187 GLenum texTarget
, GLuint level
, GLuint zoffset
)
189 remove_attachment(ctx
, att
);
190 att
->Type
= GL_TEXTURE
;
191 att
->Texture
= texObj
;
192 att
->TextureLevel
= level
;
193 if (IS_CUBE_FACE(texTarget
)) {
194 att
->CubeMapFace
= texTarget
- GL_TEXTURE_CUBE_MAP_POSITIVE_X
;
197 att
->CubeMapFace
= 0;
199 att
->Zoffset
= zoffset
;
205 set_renderbuffer_attachment(GLcontext
*ctx
,
206 struct gl_render_buffer_attachment
*att
,
207 struct gl_render_buffer_object
*rb
)
209 remove_attachment(ctx
, att
);
210 att
->Type
= GL_RENDERBUFFER_EXT
;
211 att
->Renderbuffer
= rb
;
217 _mesa_IsRenderbufferEXT(GLuint renderbuffer
)
219 struct gl_render_buffer_object
*rb
;
220 GET_CURRENT_CONTEXT(ctx
);
222 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx
, GL_FALSE
);
224 rb
= lookup_renderbuffer(ctx
, renderbuffer
);
225 return rb
? GL_TRUE
: GL_FALSE
;
230 _mesa_BindRenderbufferEXT(GLenum target
, GLuint renderbuffer
)
232 struct gl_render_buffer_object
*newRb
, *oldRb
;
233 GET_CURRENT_CONTEXT(ctx
);
235 ASSERT_OUTSIDE_BEGIN_END(ctx
);
237 if (target
!= GL_RENDERBUFFER_EXT
) {
238 _mesa_error(ctx
, GL_INVALID_ENUM
,
239 "glBindRenderbufferEXT(target)");
244 newRb
= lookup_renderbuffer(ctx
, renderbuffer
);
245 if (newRb
== &DummyRenderbuffer
) {
246 /* ID was reserved, but no real renderbuffer object made yet */
250 /* create new renderbuffer object */
251 newRb
= new_renderbuffer(ctx
, renderbuffer
);
253 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glBindRenderbufferEXT");
256 _mesa_HashInsert(ctx
->Shared
->RenderBuffers
, renderbuffer
, newRb
);
264 oldRb
= ctx
->CurrentRenderbuffer
;
267 if (oldRb
->RefCount
== 0) {
268 _mesa_free(oldRb
); /* XXX device driver function */
272 ASSERT(newRb
!= &DummyRenderbuffer
);
274 ctx
->CurrentRenderbuffer
= newRb
;
279 _mesa_DeleteRenderbuffersEXT(GLsizei n
, const GLuint
*renderbuffers
)
282 GET_CURRENT_CONTEXT(ctx
);
284 ASSERT_OUTSIDE_BEGIN_END(ctx
);
286 for (i
= 0; i
< n
; i
++) {
287 if (renderbuffers
[i
]) {
288 struct gl_render_buffer_object
*rb
;
289 rb
= lookup_renderbuffer(ctx
, renderbuffers
[i
]);
291 /* remove from hash table immediately, to free the ID */
292 _mesa_HashRemove(ctx
->Shared
->RenderBuffers
, renderbuffers
[i
]);
294 if (rb
!= &DummyRenderbuffer
) {
295 /* But the object will not be freed until it's no longer
296 * bound in any context.
299 if (rb
->RefCount
== 0) {
300 _mesa_free(rb
); /* XXX call device driver function */
310 _mesa_GenRenderbuffersEXT(GLsizei n
, GLuint
*renderbuffers
)
312 GET_CURRENT_CONTEXT(ctx
);
316 ASSERT_OUTSIDE_BEGIN_END(ctx
);
319 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGenRenderbuffersEXT(n)");
326 first
= _mesa_HashFindFreeKeyBlock(ctx
->Shared
->RenderBuffers
, n
);
328 for (i
= 0; i
< n
; i
++) {
329 GLuint name
= first
+ i
;
331 /* insert dummy placeholder into hash table */
332 _glthread_LOCK_MUTEX(ctx
->Shared
->Mutex
);
333 _mesa_HashInsert(ctx
->Shared
->RenderBuffers
, name
, &DummyRenderbuffer
);
334 _glthread_UNLOCK_MUTEX(ctx
->Shared
->Mutex
);
336 renderbuffers
[i
] = name
;
342 base_internal_format(GLcontext
*ctx
, GLenum internalFormat
)
344 switch (internalFormat
) {
351 /*case GL_LUMINANCE:*/
357 /*case GL_LUMINANCE_ALPHA:*/
358 case GL_LUMINANCE4_ALPHA4
:
359 case GL_LUMINANCE6_ALPHA2
:
360 case GL_LUMINANCE8_ALPHA8
:
361 case GL_LUMINANCE12_ALPHA4
:
362 case GL_LUMINANCE12_ALPHA12
:
363 case GL_LUMINANCE16_ALPHA16
:
364 return GL_LUMINANCE_ALPHA
;
365 /*case GL_INTENSITY:*/
389 case GL_STENCIL_INDEX1_EXT
:
390 case GL_STENCIL_INDEX4_EXT
:
391 case GL_STENCIL_INDEX8_EXT
:
392 case GL_STENCIL_INDEX16_EXT
:
393 return GL_STENCIL_INDEX
;
398 if (ctx
->Extensions
.SGIX_depth_texture
) {
399 switch (internalFormat
) {
400 /*case GL_DEPTH_COMPONENT:*/
401 case GL_DEPTH_COMPONENT16_SGIX
:
402 case GL_DEPTH_COMPONENT24_SGIX
:
403 case GL_DEPTH_COMPONENT32_SGIX
:
404 return GL_DEPTH_COMPONENT
;
415 _mesa_RenderbufferStorageEXT(GLenum target
, GLenum internalFormat
,
416 GLsizei width
, GLsizei height
)
419 GET_CURRENT_CONTEXT(ctx
);
421 ASSERT_OUTSIDE_BEGIN_END(ctx
);
423 if (target
!= GL_RENDERBUFFER_EXT
) {
424 _mesa_error(ctx
, GL_INVALID_ENUM
, "glRenderbufferStorageEXT(target)");
428 baseFormat
= base_internal_format(ctx
, internalFormat
);
429 if (baseFormat
== 0) {
430 _mesa_error(ctx
, GL_INVALID_ENUM
,
431 "glRenderbufferStorageEXT(internalFormat)");
435 if (width
< 1 || width
> ctx
->Const
.MaxRenderbufferSize
) {
436 _mesa_error(ctx
, GL_INVALID_VALUE
, "glRenderbufferStorageEXT(width)");
440 if (height
< 1 || height
> ctx
->Const
.MaxRenderbufferSize
) {
441 _mesa_error(ctx
, GL_INVALID_VALUE
, "glRenderbufferStorageEXT(height)");
445 /* XXX this check isn't in the spec, but seems necessary */
446 if (!ctx
->CurrentRenderbuffer
) {
447 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glRenderbufferStorageEXT");
451 if (ctx
->CurrentRenderbuffer
->Data
) {
452 /* XXX device driver free */
453 _mesa_free(ctx
->CurrentRenderbuffer
->Data
);
456 /* XXX device driver allocate, fix size */
457 ctx
->CurrentRenderbuffer
->Data
= _mesa_malloc(width
* height
* 4);
458 if (ctx
->CurrentRenderbuffer
->Data
== NULL
) {
459 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glRenderbufferStorageEXT");
462 ctx
->CurrentRenderbuffer
->InternalFormat
= internalFormat
;
463 ctx
->CurrentRenderbuffer
->Width
= width
;
464 ctx
->CurrentRenderbuffer
->Height
= height
;
469 _mesa_GetRenderbufferParameterivEXT(GLenum target
, GLenum pname
, GLint
*params
)
471 GET_CURRENT_CONTEXT(ctx
);
473 ASSERT_OUTSIDE_BEGIN_END(ctx
);
475 if (target
!= GL_RENDERBUFFER_EXT
) {
476 _mesa_error(ctx
, GL_INVALID_ENUM
,
477 "glGetRenderbufferParameterivEXT(target)");
481 if (!ctx
->CurrentRenderbuffer
) {
482 _mesa_error(ctx
, GL_INVALID_OPERATION
,
483 "glGetRenderbufferParameterivEXT");
488 case GL_RENDERBUFFER_WIDTH_EXT
:
489 *params
= ctx
->CurrentRenderbuffer
->Width
;
491 case GL_RENDERBUFFER_HEIGHT_EXT
:
492 *params
= ctx
->CurrentRenderbuffer
->Height
;
494 case GL_RENDERBUFFER_INTERNAL_FORMAT_EXT
:
495 *params
= ctx
->CurrentRenderbuffer
->InternalFormat
;
498 _mesa_error(ctx
, GL_INVALID_ENUM
,
499 "glGetRenderbufferParameterivEXT(target)");
506 _mesa_IsFramebufferEXT(GLuint framebuffer
)
508 struct gl_frame_buffer_object
*fb
;
509 GET_CURRENT_CONTEXT(ctx
);
511 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx
, GL_FALSE
);
513 fb
= lookup_framebuffer(ctx
, framebuffer
);
514 return fb
? GL_TRUE
: GL_FALSE
;
519 _mesa_BindFramebufferEXT(GLenum target
, GLuint framebuffer
)
521 struct gl_frame_buffer_object
*newFb
, *oldFb
;
522 GET_CURRENT_CONTEXT(ctx
);
524 ASSERT_OUTSIDE_BEGIN_END(ctx
);
526 if (target
!= GL_FRAMEBUFFER_EXT
) {
527 _mesa_error(ctx
, GL_INVALID_ENUM
,
528 "glBindFramebufferEXT(target)");
533 newFb
= lookup_framebuffer(ctx
, framebuffer
);
534 if (newFb
== &DummyFramebuffer
) {
535 /* ID was reserved, but no real framebuffer object made yet */
539 /* create new framebuffer object */
540 newFb
= new_framebuffer(ctx
, framebuffer
);
542 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glBindFramebufferEXT");
545 _mesa_HashInsert(ctx
->Shared
->FrameBuffers
, framebuffer
, newFb
);
553 oldFb
= ctx
->CurrentFramebuffer
;
556 if (oldFb
->RefCount
== 0) {
557 _mesa_free(oldFb
); /* XXX device driver function */
561 ASSERT(newFb
!= &DummyFramebuffer
);
563 ctx
->CurrentFramebuffer
= newFb
;
568 _mesa_DeleteFramebuffersEXT(GLsizei n
, const GLuint
*framebuffers
)
571 GET_CURRENT_CONTEXT(ctx
);
573 ASSERT_OUTSIDE_BEGIN_END(ctx
);
575 for (i
= 0; i
< n
; i
++) {
576 if (framebuffers
[i
]) {
577 struct gl_frame_buffer_object
*fb
;
578 fb
= lookup_framebuffer(ctx
, framebuffers
[i
]);
580 /* remove from hash table immediately, to free the ID */
581 _mesa_HashRemove(ctx
->Shared
->FrameBuffers
, framebuffers
[i
]);
583 if (fb
!= &DummyFramebuffer
) {
584 /* But the object will not be freed until it's no longer
585 * bound in any context.
588 if (fb
->RefCount
== 0) {
589 _mesa_free(fb
); /* XXX call device driver function */
599 _mesa_GenFramebuffersEXT(GLsizei n
, GLuint
*framebuffers
)
601 GET_CURRENT_CONTEXT(ctx
);
605 ASSERT_OUTSIDE_BEGIN_END(ctx
);
608 _mesa_error(ctx
, GL_INVALID_VALUE
, "glGenFramebuffersEXT(n)");
615 first
= _mesa_HashFindFreeKeyBlock(ctx
->Shared
->FrameBuffers
, n
);
617 for (i
= 0; i
< n
; i
++) {
618 GLuint name
= first
+ i
;
620 /* insert into hash table */
621 _glthread_LOCK_MUTEX(ctx
->Shared
->Mutex
);
622 _mesa_HashInsert(ctx
->Shared
->FrameBuffers
, name
, &DummyFramebuffer
);
623 _glthread_UNLOCK_MUTEX(ctx
->Shared
->Mutex
);
625 framebuffers
[i
] = name
;
632 _mesa_CheckFramebufferStatusEXT(GLenum target
)
634 GET_CURRENT_CONTEXT(ctx
);
636 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx
, GL_FRAMEBUFFER_STATUS_ERROR_EXT
);
638 if (target
!= GL_FRAMEBUFFER_EXT
) {
639 _mesa_error(ctx
, GL_INVALID_ENUM
,
640 "glCheckFramebufferStatus(target)");
641 return GL_FRAMEBUFFER_STATUS_ERROR_EXT
;
645 GL_FRAMEBUFFER_COMPLETE_EXT
646 GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT
647 GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT
648 GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT
649 GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT
650 GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT
651 GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT
652 GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT
653 GL_FRAMEBUFFER_UNSUPPORTED_EXT
654 GL_FRAMEBUFFER_STATUS_ERROR_EXT
656 return GL_FRAMEBUFFER_STATUS_ERROR_EXT
;
662 * Do error checking common to glFramebufferTexture1D/2D/3DEXT.
663 * \return GL_TRUE if any error, GL_FALSE otherwise
666 error_check_framebuffer_texture(GLcontext
*ctx
, GLuint dims
,
667 GLenum target
, GLenum attachment
,
668 GLenum textarget
, GLuint texture
, GLint level
)
670 ASSERT(dims
>= 1 && dims
<= 3);
672 if (target
!= GL_FRAMEBUFFER_EXT
) {
673 _mesa_error(ctx
, GL_INVALID_ENUM
,
674 "glFramebufferTexture%dDEXT(target)", dims
);
678 if (ctx
->CurrentFramebuffer
== NULL
) {
679 _mesa_error(ctx
, GL_INVALID_OPERATION
,
680 "glFramebufferTexture%dDEXT", dims
);
684 /* only check textarget, level if texture ID is non-zero*/
686 if ((dims
== 1 && textarget
!= GL_TEXTURE_1D
) ||
687 (dims
== 3 && textarget
!= GL_TEXTURE_3D
) ||
688 (dims
== 2 && textarget
!= GL_TEXTURE_2D
&&
689 textarget
!= GL_TEXTURE_RECTANGLE_ARB
&&
690 !IS_CUBE_FACE(textarget
))) {
691 _mesa_error(ctx
, GL_INVALID_VALUE
,
692 "glFramebufferTexture%dDEXT(textarget)", dims
);
696 if ((level
< 0) || level
>= _mesa_max_texture_levels(ctx
, textarget
)) {
697 _mesa_error(ctx
, GL_INVALID_VALUE
,
698 "glFramebufferTexture%dDEXT(level)", dims
);
708 _mesa_FramebufferTexture1DEXT(GLenum target
, GLenum attachment
,
709 GLenum textarget
, GLuint texture
, GLint level
)
711 struct gl_render_buffer_attachment
*att
;
712 GET_CURRENT_CONTEXT(ctx
);
714 ASSERT_OUTSIDE_BEGIN_END(ctx
);
716 if (error_check_framebuffer_texture(ctx
, 1, target
, attachment
,
717 textarget
, texture
, level
))
720 ASSERT(textarget
== GL_TEXTURE_1D
);
722 att
= get_attachment(ctx
, attachment
);
724 _mesa_error(ctx
, GL_INVALID_ENUM
,
725 "glFramebufferTexture1DEXT(attachment)");
730 struct gl_texture_object
*texObj
= (struct gl_texture_object
*)
731 _mesa_HashLookup(ctx
->Shared
->TexObjects
, texture
);
733 _mesa_error(ctx
, GL_INVALID_VALUE
,
734 "glFramebufferTexture1DEXT(texture)");
737 if (texObj
->Target
!= textarget
) {
738 _mesa_error(ctx
, GL_INVALID_OPERATION
, /* XXX correct error? */
739 "glFramebufferTexture1DEXT(texture target)");
742 set_texture_attachment(ctx
, att
, texObj
, textarget
, level
, 0);
745 remove_attachment(ctx
, att
);
748 /* XXX call a driver function to signal new attachment? */
753 _mesa_FramebufferTexture2DEXT(GLenum target
, GLenum attachment
,
754 GLenum textarget
, GLuint texture
, GLint level
)
756 struct gl_render_buffer_attachment
*att
;
757 GET_CURRENT_CONTEXT(ctx
);
759 ASSERT_OUTSIDE_BEGIN_END(ctx
);
761 if (error_check_framebuffer_texture(ctx
, 2, target
, attachment
,
762 textarget
, texture
, level
))
765 ASSERT(textarget
== GL_TEXTURE_2D
||
766 textarget
== GL_TEXTURE_RECTANGLE_ARB
||
767 IS_CUBE_FACE(textarget
));
769 att
= get_attachment(ctx
, attachment
);
771 _mesa_error(ctx
, GL_INVALID_ENUM
,
772 "glFramebufferTexture2DEXT(attachment)");
777 struct gl_texture_object
*texObj
= (struct gl_texture_object
*)
778 _mesa_HashLookup(ctx
->Shared
->TexObjects
, texture
);
780 _mesa_error(ctx
, GL_INVALID_VALUE
,
781 "glFramebufferTexture2DEXT(texture)");
784 if ((texObj
->Target
== GL_TEXTURE_2D
&& textarget
!= GL_TEXTURE_2D
) ||
785 (texObj
->Target
== GL_TEXTURE_RECTANGLE_ARB
786 && textarget
!= GL_TEXTURE_RECTANGLE_ARB
) ||
787 (texObj
->Target
== GL_TEXTURE_CUBE_MAP
788 && !IS_CUBE_FACE(textarget
))) {
789 _mesa_error(ctx
, GL_INVALID_OPERATION
, /* XXX correct error? */
790 "glFramebufferTexture2DEXT(texture target)");
793 set_texture_attachment(ctx
, att
, texObj
, textarget
, level
, 0);
796 remove_attachment(ctx
, att
);
803 _mesa_FramebufferTexture3DEXT(GLenum target
, GLenum attachment
,
804 GLenum textarget
, GLuint texture
,
805 GLint level
, GLint zoffset
)
807 struct gl_render_buffer_attachment
*att
;
808 GET_CURRENT_CONTEXT(ctx
);
810 ASSERT_OUTSIDE_BEGIN_END(ctx
);
812 if (error_check_framebuffer_texture(ctx
, 3, target
, attachment
,
813 textarget
, texture
, level
))
816 ASSERT(textarget
== GL_TEXTURE_3D
);
818 att
= get_attachment(ctx
, attachment
);
820 _mesa_error(ctx
, GL_INVALID_ENUM
,
821 "glFramebufferTexture1DEXT(attachment)");
826 struct gl_texture_object
*texObj
= (struct gl_texture_object
*)
827 _mesa_HashLookup(ctx
->Shared
->TexObjects
, texture
);
829 _mesa_error(ctx
, GL_INVALID_VALUE
,
830 "glFramebufferTexture3DEXT(texture)");
833 if (texObj
->Target
!= textarget
) {
834 _mesa_error(ctx
, GL_INVALID_OPERATION
, /* XXX correct error? */
835 "glFramebufferTexture3DEXT(texture target)");
838 if (zoffset
>= texObj
->Image
[0][level
]->Depth
) {
839 _mesa_error(ctx
, GL_INVALID_VALUE
,
840 "glFramebufferTexture3DEXT(zoffset)");
843 set_texture_attachment(ctx
, att
, texObj
, textarget
, level
, zoffset
);
846 remove_attachment(ctx
, att
);
852 _mesa_FramebufferRenderbufferEXT(GLenum target
, GLenum attachment
,
853 GLenum renderbufferTarget
,
856 struct gl_render_buffer_attachment
*att
;
857 GET_CURRENT_CONTEXT(ctx
);
859 ASSERT_OUTSIDE_BEGIN_END(ctx
);
861 if (target
!= GL_FRAMEBUFFER_EXT
) {
862 _mesa_error(ctx
, GL_INVALID_ENUM
,
863 "glFramebufferRenderbufferEXT(target)");
867 if (renderbufferTarget
!= GL_RENDERBUFFER_EXT
) {
868 _mesa_error(ctx
, GL_INVALID_ENUM
,
869 "glFramebufferRenderbufferEXT(renderbufferTarget)");
873 if (ctx
->CurrentFramebuffer
== NULL
) {
874 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glFramebufferRenderbufferEXT");
878 att
= get_attachment(ctx
, attachment
);
880 _mesa_error(ctx
, GL_INVALID_ENUM
,
881 "glFramebufferRenderbufferEXT(attachment)");
886 struct gl_render_buffer_object
*rb
;
887 rb
= lookup_renderbuffer(ctx
, renderbuffer
);
889 _mesa_error(ctx
, GL_INVALID_VALUE
,
890 "glFramebufferRenderbufferEXT(renderbuffer)");
893 set_renderbuffer_attachment(ctx
, att
, rb
);
896 remove_attachment(ctx
, att
);
902 _mesa_GetFramebufferAttachmentParameterivEXT(GLenum target
, GLenum attachment
,
903 GLenum pname
, GLint
*params
)
905 const struct gl_render_buffer_attachment
*att
;
906 GET_CURRENT_CONTEXT(ctx
);
908 ASSERT_OUTSIDE_BEGIN_END(ctx
);
910 if (target
!= GL_FRAMEBUFFER_EXT
) {
911 _mesa_error(ctx
, GL_INVALID_ENUM
,
912 "glGetFramebufferAttachmentParameterivEXT(target)");
916 if (ctx
->CurrentFramebuffer
== NULL
) {
917 _mesa_error(ctx
, GL_INVALID_OPERATION
,
918 "glGetFramebufferAttachmentParameterivEXT");
922 att
= get_attachment(ctx
, attachment
);
924 _mesa_error(ctx
, GL_INVALID_ENUM
,
925 "glGetFramebufferAttachmentParameterivEXT(attachment)");
930 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT
:
933 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT
:
934 if (att
->Type
== GL_RENDERBUFFER_EXT
) {
935 *params
= att
->Renderbuffer
->Name
;
937 else if (att
->Type
== GL_TEXTURE
) {
938 *params
= att
->Texture
->Name
;
941 _mesa_error(ctx
, GL_INVALID_ENUM
,
942 "glGetFramebufferAttachmentParameterivEXT(pname)");
945 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT
:
946 if (att
->Type
== GL_TEXTURE
) {
947 *params
= att
->TextureLevel
;
950 _mesa_error(ctx
, GL_INVALID_ENUM
,
951 "glGetFramebufferAttachmentParameterivEXT(pname)");
954 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT
:
955 if (att
->Type
== GL_TEXTURE
) {
956 *params
= GL_TEXTURE_CUBE_MAP_POSITIVE_X
+ att
->CubeMapFace
;
959 _mesa_error(ctx
, GL_INVALID_ENUM
,
960 "glGetFramebufferAttachmentParameterivEXT(pname)");
963 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT
:
964 if (att
->Type
== GL_TEXTURE
) {
965 *params
= att
->Zoffset
;
968 _mesa_error(ctx
, GL_INVALID_ENUM
,
969 "glGetFramebufferAttachmentParameterivEXT(pname)");
973 _mesa_error(ctx
, GL_INVALID_ENUM
,
974 "glGetFramebufferAttachmentParameterivEXT(pname)");
981 _mesa_GenerateMipmapEXT(GLenum target
)
983 struct gl_texture_unit
*texUnit
;
984 struct gl_texture_object
*texObj
;
985 GET_CURRENT_CONTEXT(ctx
);
987 ASSERT_OUTSIDE_BEGIN_END(ctx
);
993 case GL_TEXTURE_CUBE_MAP
:
996 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGenerateMipmapEXT(target)");
1000 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
1001 texObj
= _mesa_select_tex_object(ctx
, texUnit
, target
);
1003 /* XXX this might not handle cube maps correctly */
1004 _mesa_generate_mipmap(ctx
, target
, texUnit
, texObj
);