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);