Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4358 Serge 1
/*
2
 * Mesa 3-D graphics library
3
 *
4
 * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
5
 * Copyright (C) 1999-2009  VMware, Inc.  All Rights Reserved.
6
 *
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:
13
 *
14
 * The above copyright notice and this permission notice shall be included
15
 * in all copies or substantial portions of the Software.
16
 *
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
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23
 * OTHER DEALINGS IN THE SOFTWARE.
24
 */
25
 
26
 
27
/*
28
 * GL_EXT/ARB_framebuffer_object extensions
29
 *
30
 * Authors:
31
 *   Brian Paul
32
 */
33
 
34
#include 
35
 
36
#include "buffers.h"
37
#include "context.h"
38
#include "enums.h"
39
#include "fbobject.h"
40
#include "formats.h"
41
#include "framebuffer.h"
42
#include "glformats.h"
43
#include "hash.h"
44
#include "macros.h"
45
#include "multisample.h"
46
#include "mtypes.h"
47
#include "renderbuffer.h"
48
#include "state.h"
49
#include "teximage.h"
50
#include "texobj.h"
51
 
52
 
53
/** Set this to 1 to debug/log glBlitFramebuffer() calls */
54
#define DEBUG_BLIT 0
55
 
56
 
57
/**
58
 * Notes:
59
 *
60
 * None of the GL_EXT_framebuffer_object functions are compiled into
61
 * display lists.
62
 */
63
 
64
 
65
 
66
/*
67
 * When glGenRender/FramebuffersEXT() is called we insert pointers to
68
 * these placeholder objects into the hash table.
69
 * Later, when the object ID is first bound, we replace the placeholder
70
 * with the real frame/renderbuffer.
71
 */
72
static struct gl_framebuffer DummyFramebuffer;
73
static struct gl_renderbuffer DummyRenderbuffer;
74
 
75
/* We bind this framebuffer when applications pass a NULL
76
 * drawable/surface in make current. */
77
static struct gl_framebuffer IncompleteFramebuffer;
78
 
79
 
80
static void
81
delete_dummy_renderbuffer(struct gl_context *ctx, struct gl_renderbuffer *rb)
82
{
83
   /* no op */
84
}
85
 
86
static void
87
delete_dummy_framebuffer(struct gl_framebuffer *fb)
88
{
89
   /* no op */
90
}
91
 
92
 
93
void
94
_mesa_init_fbobjects(struct gl_context *ctx)
95
{
96
   _glthread_INIT_MUTEX(DummyFramebuffer.Mutex);
97
   _glthread_INIT_MUTEX(DummyRenderbuffer.Mutex);
98
   _glthread_INIT_MUTEX(IncompleteFramebuffer.Mutex);
99
   DummyFramebuffer.Delete = delete_dummy_framebuffer;
100
   DummyRenderbuffer.Delete = delete_dummy_renderbuffer;
101
   IncompleteFramebuffer.Delete = delete_dummy_framebuffer;
102
}
103
 
104
struct gl_framebuffer *
105
_mesa_get_incomplete_framebuffer(void)
106
{
107
   return &IncompleteFramebuffer;
108
}
109
 
110
/**
111
 * Helper routine for getting a gl_renderbuffer.
112
 */
113
struct gl_renderbuffer *
114
_mesa_lookup_renderbuffer(struct gl_context *ctx, GLuint id)
115
{
116
   struct gl_renderbuffer *rb;
117
 
118
   if (id == 0)
119
      return NULL;
120
 
121
   rb = (struct gl_renderbuffer *)
122
      _mesa_HashLookup(ctx->Shared->RenderBuffers, id);
123
   return rb;
124
}
125
 
126
 
127
/**
128
 * Helper routine for getting a gl_framebuffer.
129
 */
130
struct gl_framebuffer *
131
_mesa_lookup_framebuffer(struct gl_context *ctx, GLuint id)
132
{
133
   struct gl_framebuffer *fb;
134
 
135
   if (id == 0)
136
      return NULL;
137
 
138
   fb = (struct gl_framebuffer *)
139
      _mesa_HashLookup(ctx->Shared->FrameBuffers, id);
140
   return fb;
141
}
142
 
143
 
144
/**
145
 * Mark the given framebuffer as invalid.  This will force the
146
 * test for framebuffer completeness to be done before the framebuffer
147
 * is used.
148
 */
149
static void
150
invalidate_framebuffer(struct gl_framebuffer *fb)
151
{
152
   fb->_Status = 0; /* "indeterminate" */
153
}
154
 
155
 
156
/**
157
 * Return the gl_framebuffer object which corresponds to the given
158
 * framebuffer target, such as GL_DRAW_FRAMEBUFFER.
159
 * Check support for GL_EXT_framebuffer_blit to determine if certain
160
 * targets are legal.
161
 * \return gl_framebuffer pointer or NULL if target is illegal
162
 */
163
static struct gl_framebuffer *
164
get_framebuffer_target(struct gl_context *ctx, GLenum target)
165
{
166
   bool have_fb_blit = _mesa_is_gles3(ctx) ||
167
      (ctx->Extensions.EXT_framebuffer_blit && _mesa_is_desktop_gl(ctx));
168
   switch (target) {
169
   case GL_DRAW_FRAMEBUFFER:
170
      return have_fb_blit ? ctx->DrawBuffer : NULL;
171
   case GL_READ_FRAMEBUFFER:
172
      return have_fb_blit ? ctx->ReadBuffer : NULL;
173
   case GL_FRAMEBUFFER_EXT:
174
      return ctx->DrawBuffer;
175
   default:
176
      return NULL;
177
   }
178
}
179
 
180
 
181
/**
182
 * Given a GL_*_ATTACHMENTn token, return a pointer to the corresponding
183
 * gl_renderbuffer_attachment object.
184
 * This function is only used for user-created FB objects, not the
185
 * default / window-system FB object.
186
 * If \p attachment is GL_DEPTH_STENCIL_ATTACHMENT, return a pointer to
187
 * the depth buffer attachment point.
188
 */
189
struct gl_renderbuffer_attachment *
190
_mesa_get_attachment(struct gl_context *ctx, struct gl_framebuffer *fb,
191
                     GLenum attachment)
192
{
193
   GLuint i;
194
 
195
   assert(_mesa_is_user_fbo(fb));
196
 
197
   switch (attachment) {
198
   case GL_COLOR_ATTACHMENT0_EXT:
199
   case GL_COLOR_ATTACHMENT1_EXT:
200
   case GL_COLOR_ATTACHMENT2_EXT:
201
   case GL_COLOR_ATTACHMENT3_EXT:
202
   case GL_COLOR_ATTACHMENT4_EXT:
203
   case GL_COLOR_ATTACHMENT5_EXT:
204
   case GL_COLOR_ATTACHMENT6_EXT:
205
   case GL_COLOR_ATTACHMENT7_EXT:
206
   case GL_COLOR_ATTACHMENT8_EXT:
207
   case GL_COLOR_ATTACHMENT9_EXT:
208
   case GL_COLOR_ATTACHMENT10_EXT:
209
   case GL_COLOR_ATTACHMENT11_EXT:
210
   case GL_COLOR_ATTACHMENT12_EXT:
211
   case GL_COLOR_ATTACHMENT13_EXT:
212
   case GL_COLOR_ATTACHMENT14_EXT:
213
   case GL_COLOR_ATTACHMENT15_EXT:
214
      /* Only OpenGL ES 1.x forbids color attachments other than
215
       * GL_COLOR_ATTACHMENT0.  For all other APIs the limit set by the
216
       * hardware is used.
217
       */
218
      i = attachment - GL_COLOR_ATTACHMENT0_EXT;
219
      if (i >= ctx->Const.MaxColorAttachments
220
	  || (i > 0 && ctx->API == API_OPENGLES)) {
221
	 return NULL;
222
      }
223
      return &fb->Attachment[BUFFER_COLOR0 + i];
224
   case GL_DEPTH_STENCIL_ATTACHMENT:
225
      if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx))
226
	 return NULL;
227
      /* fall-through */
228
   case GL_DEPTH_ATTACHMENT_EXT:
229
      return &fb->Attachment[BUFFER_DEPTH];
230
   case GL_STENCIL_ATTACHMENT_EXT:
231
      return &fb->Attachment[BUFFER_STENCIL];
232
   default:
233
      return NULL;
234
   }
235
}
236
 
237
 
238
/**
239
 * As above, but only used for getting attachments of the default /
240
 * window-system framebuffer (not user-created framebuffer objects).
241
 */
242
static struct gl_renderbuffer_attachment *
243
_mesa_get_fb0_attachment(struct gl_context *ctx, struct gl_framebuffer *fb,
244
                         GLenum attachment)
245
{
246
   assert(_mesa_is_winsys_fbo(fb));
247
 
248
   if (_mesa_is_gles3(ctx)) {
249
      assert(attachment == GL_BACK ||
250
             attachment == GL_DEPTH ||
251
             attachment == GL_STENCIL);
252
      switch (attachment) {
253
      case GL_BACK:
254
         /* Since there is no stereo rendering in ES 3.0, only return the
255
          * LEFT bits.
256
          */
257
         if (ctx->DrawBuffer->Visual.doubleBufferMode)
258
            return &fb->Attachment[BUFFER_BACK_LEFT];
259
         return &fb->Attachment[BUFFER_FRONT_LEFT];
260
      case GL_DEPTH:
261
      return &fb->Attachment[BUFFER_DEPTH];
262
      case GL_STENCIL:
263
         return &fb->Attachment[BUFFER_STENCIL];
264
      }
265
   }
266
 
267
   switch (attachment) {
268
   case GL_FRONT_LEFT:
269
      return &fb->Attachment[BUFFER_FRONT_LEFT];
270
   case GL_FRONT_RIGHT:
271
      return &fb->Attachment[BUFFER_FRONT_RIGHT];
272
   case GL_BACK_LEFT:
273
      return &fb->Attachment[BUFFER_BACK_LEFT];
274
   case GL_BACK_RIGHT:
275
      return &fb->Attachment[BUFFER_BACK_RIGHT];
276
   case GL_AUX0:
277
      if (fb->Visual.numAuxBuffers == 1) {
278
         return &fb->Attachment[BUFFER_AUX0];
279
      }
280
      return NULL;
281
 
282
   /* Page 336 (page 352 of the PDF) of the OpenGL 3.0 spec says:
283
    *
284
    *     "If the default framebuffer is bound to target, then attachment must
285
    *     be one of FRONT LEFT, FRONT RIGHT, BACK LEFT, BACK RIGHT, or AUXi,
286
    *     identifying a color buffer; DEPTH, identifying the depth buffer; or
287
    *     STENCIL, identifying the stencil buffer."
288
    *
289
    * Revision #34 of the ARB_framebuffer_object spec has essentially the same
290
    * language.  However, revision #33 of the ARB_framebuffer_object spec
291
    * says:
292
    *
293
    *     "If the default framebuffer is bound to , then 
294
    *     must be one of FRONT_LEFT, FRONT_RIGHT, BACK_LEFT, BACK_RIGHT, AUXi,
295
    *     DEPTH_BUFFER, or STENCIL_BUFFER, identifying a color buffer, the
296
    *     depth buffer, or the stencil buffer, and  may be
297
    *     FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE or
298
    *     FRAMEBUFFER_ATTACHMENT_OBJECT_NAME."
299
    *
300
    * The enum values for DEPTH_BUFFER and STENCIL_BUFFER have been removed
301
    * from glext.h, so shipping apps should not use those values.
302
    *
303
    * Note that neither EXT_framebuffer_object nor OES_framebuffer_object
304
    * support queries of the window system FBO.
305
    */
306
   case GL_DEPTH:
307
      return &fb->Attachment[BUFFER_DEPTH];
308
   case GL_STENCIL:
309
      return &fb->Attachment[BUFFER_STENCIL];
310
   default:
311
      return NULL;
312
   }
313
}
314
 
315
 
316
 
317
/**
318
 * Remove any texture or renderbuffer attached to the given attachment
319
 * point.  Update reference counts, etc.
320
 */
321
void
322
_mesa_remove_attachment(struct gl_context *ctx,
323
                        struct gl_renderbuffer_attachment *att)
324
{
325
   struct gl_renderbuffer *rb = att->Renderbuffer;
326
 
327
   /* tell driver that we're done rendering to this texture. */
328
   if (rb && rb->NeedsFinishRenderTexture)
329
      ctx->Driver.FinishRenderTexture(ctx, rb);
330
 
331
   if (att->Type == GL_TEXTURE) {
332
      ASSERT(att->Texture);
333
      _mesa_reference_texobj(&att->Texture, NULL); /* unbind */
334
      ASSERT(!att->Texture);
335
   }
336
   if (att->Type == GL_TEXTURE || att->Type == GL_RENDERBUFFER_EXT) {
337
      ASSERT(!att->Texture);
338
      _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); /* unbind */
339
      ASSERT(!att->Renderbuffer);
340
   }
341
   att->Type = GL_NONE;
342
   att->Complete = GL_TRUE;
343
}
344
 
345
/**
346
 * Verify a couple error conditions that will lead to an incomplete FBO and
347
 * may cause problems for the driver's RenderTexture path.
348
 */
349
static bool
350
driver_RenderTexture_is_safe(const struct gl_renderbuffer_attachment *att)
351
{
352
   const struct gl_texture_image *const texImage =
353
      att->Texture->Image[att->CubeMapFace][att->TextureLevel];
354
 
355
   if (texImage->Width == 0 || texImage->Height == 0 || texImage->Depth == 0)
356
      return false;
357
 
358
   if ((texImage->TexObject->Target == GL_TEXTURE_1D_ARRAY
359
        && att->Zoffset >= texImage->Height)
360
       || (texImage->TexObject->Target != GL_TEXTURE_1D_ARRAY
361
           && att->Zoffset >= texImage->Depth))
362
      return false;
363
 
364
   return true;
365
}
366
 
367
/**
368
 * Create a renderbuffer which will be set up by the driver to wrap the
369
 * texture image slice.
370
 *
371
 * By using a gl_renderbuffer (like user-allocated renderbuffers), drivers get
372
 * to share most of their framebuffer rendering code between winsys,
373
 * renderbuffer, and texture attachments.
374
 *
375
 * The allocated renderbuffer uses a non-zero Name so that drivers can check
376
 * it for determining vertical orientation, but we use ~0 to make it fairly
377
 * unambiguous with actual user (non-texture) renderbuffers.
378
 */
379
void
380
_mesa_update_texture_renderbuffer(struct gl_context *ctx,
381
                                  struct gl_framebuffer *fb,
382
                                  struct gl_renderbuffer_attachment *att)
383
{
384
   struct gl_texture_image *texImage;
385
   struct gl_renderbuffer *rb;
386
 
387
   texImage = att->Texture->Image[att->CubeMapFace][att->TextureLevel];
388
 
389
   rb = att->Renderbuffer;
390
   if (!rb) {
391
      rb = ctx->Driver.NewRenderbuffer(ctx, ~0);
392
      if (!rb) {
393
         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glFramebufferTexture()");
394
         return;
395
      }
396
      _mesa_reference_renderbuffer(&att->Renderbuffer, rb);
397
 
398
      /* This can't get called on a texture renderbuffer, so set it to NULL
399
       * for clarity compared to user renderbuffers.
400
       */
401
      rb->AllocStorage = NULL;
402
 
403
      rb->NeedsFinishRenderTexture = ctx->Driver.FinishRenderTexture != NULL;
404
   }
405
 
406
   if (!texImage)
407
      return;
408
 
409
   rb->_BaseFormat = texImage->_BaseFormat;
410
   rb->Format = texImage->TexFormat;
411
   rb->InternalFormat = texImage->InternalFormat;
412
   rb->Width = texImage->Width2;
413
   rb->Height = texImage->Height2;
414
   rb->NumSamples = texImage->NumSamples;
415
   rb->TexImage = texImage;
416
 
417
   if (driver_RenderTexture_is_safe(att))
418
      ctx->Driver.RenderTexture(ctx, fb, att);
419
}
420
 
421
/**
422
 * Bind a texture object to an attachment point.
423
 * The previous binding, if any, will be removed first.
424
 */
425
void
426
_mesa_set_texture_attachment(struct gl_context *ctx,
427
                             struct gl_framebuffer *fb,
428
                             struct gl_renderbuffer_attachment *att,
429
                             struct gl_texture_object *texObj,
430
                             GLenum texTarget, GLuint level, GLuint zoffset,
431
                             GLboolean layered)
432
{
433
   struct gl_renderbuffer *rb = att->Renderbuffer;
434
 
435
   if (rb && rb->NeedsFinishRenderTexture)
436
      ctx->Driver.FinishRenderTexture(ctx, rb);
437
 
438
   if (att->Texture == texObj) {
439
      /* re-attaching same texture */
440
      ASSERT(att->Type == GL_TEXTURE);
441
   }
442
   else {
443
      /* new attachment */
444
      _mesa_remove_attachment(ctx, att);
445
      att->Type = GL_TEXTURE;
446
      assert(!att->Texture);
447
      _mesa_reference_texobj(&att->Texture, texObj);
448
   }
449
   invalidate_framebuffer(fb);
450
 
451
   /* always update these fields */
452
   att->TextureLevel = level;
453
   att->CubeMapFace = _mesa_tex_target_to_face(texTarget);
454
   att->Zoffset = zoffset;
455
   att->Layered = layered;
456
   att->Complete = GL_FALSE;
457
 
458
   _mesa_update_texture_renderbuffer(ctx, fb, att);
459
}
460
 
461
 
462
/**
463
 * Bind a renderbuffer to an attachment point.
464
 * The previous binding, if any, will be removed first.
465
 */
466
void
467
_mesa_set_renderbuffer_attachment(struct gl_context *ctx,
468
                                  struct gl_renderbuffer_attachment *att,
469
                                  struct gl_renderbuffer *rb)
470
{
471
   /* XXX check if re-doing same attachment, exit early */
472
   _mesa_remove_attachment(ctx, att);
473
   att->Type = GL_RENDERBUFFER_EXT;
474
   att->Texture = NULL; /* just to be safe */
475
   att->Complete = GL_FALSE;
476
   _mesa_reference_renderbuffer(&att->Renderbuffer, rb);
477
}
478
 
479
 
480
/**
481
 * Fallback for ctx->Driver.FramebufferRenderbuffer()
482
 * Attach a renderbuffer object to a framebuffer object.
483
 */
484
void
485
_mesa_framebuffer_renderbuffer(struct gl_context *ctx,
486
                               struct gl_framebuffer *fb,
487
                               GLenum attachment, struct gl_renderbuffer *rb)
488
{
489
   struct gl_renderbuffer_attachment *att;
490
 
491
   _glthread_LOCK_MUTEX(fb->Mutex);
492
 
493
   att = _mesa_get_attachment(ctx, fb, attachment);
494
   ASSERT(att);
495
   if (rb) {
496
      _mesa_set_renderbuffer_attachment(ctx, att, rb);
497
      if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
498
         /* do stencil attachment here (depth already done above) */
499
         att = _mesa_get_attachment(ctx, fb, GL_STENCIL_ATTACHMENT_EXT);
500
         assert(att);
501
         _mesa_set_renderbuffer_attachment(ctx, att, rb);
502
      }
503
      rb->AttachedAnytime = GL_TRUE;
504
   }
505
   else {
506
      _mesa_remove_attachment(ctx, att);
507
   }
508
 
509
   invalidate_framebuffer(fb);
510
 
511
   _glthread_UNLOCK_MUTEX(fb->Mutex);
512
}
513
 
514
 
515
/**
516
 * Fallback for ctx->Driver.ValidateFramebuffer()
517
 * Check if the renderbuffer's formats are supported by the software
518
 * renderer.
519
 * Drivers should probably override this.
520
 */
521
void
522
_mesa_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)
523
{
524
   gl_buffer_index buf;
525
   for (buf = 0; buf < BUFFER_COUNT; buf++) {
526
      const struct gl_renderbuffer *rb = fb->Attachment[buf].Renderbuffer;
527
      if (rb) {
528
         switch (rb->_BaseFormat) {
529
         case GL_ALPHA:
530
         case GL_LUMINANCE_ALPHA:
531
         case GL_LUMINANCE:
532
         case GL_INTENSITY:
533
         case GL_RED:
534
         case GL_RG:
535
            fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED;
536
            return;
537
 
538
         default:
539
            switch (rb->Format) {
540
            /* XXX This list is likely incomplete. */
541
            case MESA_FORMAT_RGB9_E5_FLOAT:
542
               fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED;
543
               return;
544
            default:;
545
               /* render buffer format is supported by software rendering */
546
            }
547
         }
548
      }
549
   }
550
}
551
 
552
 
553
/**
554
 * Return true if the framebuffer has a combined depth/stencil
555
 * renderbuffer attached.
556
 */
557
GLboolean
558
_mesa_has_depthstencil_combined(const struct gl_framebuffer *fb)
559
{
560
   const struct gl_renderbuffer_attachment *depth =
561
         &fb->Attachment[BUFFER_DEPTH];
562
   const struct gl_renderbuffer_attachment *stencil =
563
         &fb->Attachment[BUFFER_STENCIL];
564
 
565
   if (depth->Type == stencil->Type) {
566
      if (depth->Type == GL_RENDERBUFFER_EXT &&
567
          depth->Renderbuffer == stencil->Renderbuffer)
568
         return GL_TRUE;
569
 
570
      if (depth->Type == GL_TEXTURE &&
571
          depth->Texture == stencil->Texture)
572
         return GL_TRUE;
573
   }
574
 
575
   return GL_FALSE;
576
}
577
 
578
 
579
/**
580
 * For debug only.
581
 */
582
static void
583
att_incomplete(const char *msg)
584
{
585
   if (MESA_DEBUG_FLAGS & DEBUG_INCOMPLETE_FBO) {
586
      _mesa_debug(NULL, "attachment incomplete: %s\n", msg);
587
   }
588
}
589
 
590
 
591
/**
592
 * For debug only.
593
 */
594
static void
595
fbo_incomplete(struct gl_context *ctx, const char *msg, int index)
596
{
597
   static GLuint msg_id;
598
 
599
   _mesa_gl_debug(ctx, &msg_id,
600
                  MESA_DEBUG_TYPE_OTHER,
601
                  MESA_DEBUG_SEVERITY_MEDIUM,
602
                  "FBO incomplete: %s [%d]\n", msg, index);
603
 
604
   if (MESA_DEBUG_FLAGS & DEBUG_INCOMPLETE_FBO) {
605
      _mesa_debug(NULL, "FBO Incomplete: %s [%d]\n", msg, index);
606
   }
607
}
608
 
609
 
610
/**
611
 * Is the given base format a legal format for a color renderbuffer?
612
 */
613
GLboolean
614
_mesa_is_legal_color_format(const struct gl_context *ctx, GLenum baseFormat)
615
{
616
   switch (baseFormat) {
617
   case GL_RGB:
618
   case GL_RGBA:
619
      return GL_TRUE;
620
   case GL_LUMINANCE:
621
   case GL_LUMINANCE_ALPHA:
622
   case GL_INTENSITY:
623
   case GL_ALPHA:
624
      return ctx->API == API_OPENGL_COMPAT &&
625
             ctx->Extensions.ARB_framebuffer_object;
626
   case GL_RED:
627
   case GL_RG:
628
      return ctx->Extensions.ARB_texture_rg;
629
   default:
630
      return GL_FALSE;
631
   }
632
}
633
 
634
 
635
/**
636
 * Is the given base format a legal format for a color renderbuffer?
637
 */
638
static GLboolean
639
is_format_color_renderable(const struct gl_context *ctx, gl_format format, GLenum internalFormat)
640
{
641
   const GLenum baseFormat =
642
      _mesa_get_format_base_format(format);
643
   GLboolean valid;
644
 
645
   valid = _mesa_is_legal_color_format(ctx, baseFormat);
646
   if (!valid || _mesa_is_desktop_gl(ctx)) {
647
      return valid;
648
   }
649
 
650
   /* Reject additional cases for GLES */
651
   switch (internalFormat) {
652
   case GL_RGBA8_SNORM:
653
   case GL_RGB32F:
654
   case GL_RGB32I:
655
   case GL_RGB32UI:
656
   case GL_RGB16F:
657
   case GL_RGB16I:
658
   case GL_RGB16UI:
659
   case GL_RGB8_SNORM:
660
   case GL_RGB8I:
661
   case GL_RGB8UI:
662
   case GL_SRGB8:
663
   case GL_RGB9_E5:
664
   case GL_RG8_SNORM:
665
   case GL_R8_SNORM:
666
      return GL_FALSE;
667
   default:
668
      break;
669
   }
670
 
671
   if (format == MESA_FORMAT_ARGB2101010 && internalFormat != GL_RGB10_A2) {
672
      return GL_FALSE;
673
   }
674
 
675
   return GL_TRUE;
676
}
677
 
678
 
679
/**
680
 * Is the given base format a legal format for a depth/stencil renderbuffer?
681
 */
682
static GLboolean
683
is_legal_depth_format(const struct gl_context *ctx, GLenum baseFormat)
684
{
685
   switch (baseFormat) {
686
   case GL_DEPTH_COMPONENT:
687
   case GL_DEPTH_STENCIL_EXT:
688
      return GL_TRUE;
689
   default:
690
      return GL_FALSE;
691
   }
692
}
693
 
694
 
695
/**
696
 * Test if an attachment point is complete and update its Complete field.
697
 * \param format if GL_COLOR, this is a color attachment point,
698
 *               if GL_DEPTH, this is a depth component attachment point,
699
 *               if GL_STENCIL, this is a stencil component attachment point.
700
 */
701
static void
702
test_attachment_completeness(const struct gl_context *ctx, GLenum format,
703
                             struct gl_renderbuffer_attachment *att)
704
{
705
   assert(format == GL_COLOR || format == GL_DEPTH || format == GL_STENCIL);
706
 
707
   /* assume complete */
708
   att->Complete = GL_TRUE;
709
 
710
   /* Look for reasons why the attachment might be incomplete */
711
   if (att->Type == GL_TEXTURE) {
712
      const struct gl_texture_object *texObj = att->Texture;
713
      struct gl_texture_image *texImage;
714
      GLenum baseFormat;
715
 
716
      if (!texObj) {
717
         att_incomplete("no texobj");
718
         att->Complete = GL_FALSE;
719
         return;
720
      }
721
 
722
      texImage = texObj->Image[att->CubeMapFace][att->TextureLevel];
723
      if (!texImage) {
724
         att_incomplete("no teximage");
725
         att->Complete = GL_FALSE;
726
         return;
727
      }
728
      if (texImage->Width < 1 || texImage->Height < 1) {
729
         att_incomplete("teximage width/height=0");
730
         att->Complete = GL_FALSE;
731
         return;
732
      }
733
 
734
      switch (texObj->Target) {
735
      case GL_TEXTURE_3D:
736
         if (att->Zoffset >= texImage->Depth) {
737
            att_incomplete("bad z offset");
738
            att->Complete = GL_FALSE;
739
            return;
740
         }
741
         break;
742
      case GL_TEXTURE_1D_ARRAY:
743
         if (att->Zoffset >= texImage->Height) {
744
            att_incomplete("bad 1D-array layer");
745
            att->Complete = GL_FALSE;
746
            return;
747
         }
748
         break;
749
      case GL_TEXTURE_2D_ARRAY:
750
         if (att->Zoffset >= texImage->Depth) {
751
            att_incomplete("bad 2D-array layer");
752
            att->Complete = GL_FALSE;
753
            return;
754
         }
755
         break;
756
      case GL_TEXTURE_CUBE_MAP_ARRAY:
757
         if (att->Zoffset >= texImage->Depth) {
758
            att_incomplete("bad cube-array layer");
759
            att->Complete = GL_FALSE;
760
            return;
761
         }
762
         break;
763
      }
764
 
765
      baseFormat = _mesa_get_format_base_format(texImage->TexFormat);
766
 
767
      if (format == GL_COLOR) {
768
         if (!_mesa_is_legal_color_format(ctx, baseFormat)) {
769
            att_incomplete("bad format");
770
            att->Complete = GL_FALSE;
771
            return;
772
         }
773
         if (_mesa_is_format_compressed(texImage->TexFormat)) {
774
            att_incomplete("compressed internalformat");
775
            att->Complete = GL_FALSE;
776
            return;
777
         }
778
      }
779
      else if (format == GL_DEPTH) {
780
         if (baseFormat == GL_DEPTH_COMPONENT) {
781
            /* OK */
782
         }
783
         else if (ctx->Extensions.EXT_packed_depth_stencil &&
784
                  ctx->Extensions.ARB_depth_texture &&
785
                  baseFormat == GL_DEPTH_STENCIL_EXT) {
786
            /* OK */
787
         }
788
         else {
789
            att->Complete = GL_FALSE;
790
            att_incomplete("bad depth format");
791
            return;
792
         }
793
      }
794
      else {
795
         ASSERT(format == GL_STENCIL);
796
         if (ctx->Extensions.EXT_packed_depth_stencil &&
797
             ctx->Extensions.ARB_depth_texture &&
798
             baseFormat == GL_DEPTH_STENCIL_EXT) {
799
            /* OK */
800
         }
801
         else {
802
            /* no such thing as stencil-only textures */
803
            att_incomplete("illegal stencil texture");
804
            att->Complete = GL_FALSE;
805
            return;
806
         }
807
      }
808
   }
809
   else if (att->Type == GL_RENDERBUFFER_EXT) {
810
      const GLenum baseFormat =
811
         _mesa_get_format_base_format(att->Renderbuffer->Format);
812
 
813
      ASSERT(att->Renderbuffer);
814
      if (!att->Renderbuffer->InternalFormat ||
815
          att->Renderbuffer->Width < 1 ||
816
          att->Renderbuffer->Height < 1) {
817
         att_incomplete("0x0 renderbuffer");
818
         att->Complete = GL_FALSE;
819
         return;
820
      }
821
      if (format == GL_COLOR) {
822
         if (!_mesa_is_legal_color_format(ctx, baseFormat)) {
823
            att_incomplete("bad renderbuffer color format");
824
            att->Complete = GL_FALSE;
825
            return;
826
         }
827
      }
828
      else if (format == GL_DEPTH) {
829
         if (baseFormat == GL_DEPTH_COMPONENT) {
830
            /* OK */
831
         }
832
         else if (ctx->Extensions.EXT_packed_depth_stencil &&
833
                  baseFormat == GL_DEPTH_STENCIL_EXT) {
834
            /* OK */
835
         }
836
         else {
837
            att_incomplete("bad renderbuffer depth format");
838
            att->Complete = GL_FALSE;
839
            return;
840
         }
841
      }
842
      else {
843
         assert(format == GL_STENCIL);
844
         if (baseFormat == GL_STENCIL_INDEX) {
845
            /* OK */
846
         }
847
         else if (ctx->Extensions.EXT_packed_depth_stencil &&
848
                  baseFormat == GL_DEPTH_STENCIL_EXT) {
849
            /* OK */
850
         }
851
         else {
852
            att->Complete = GL_FALSE;
853
            att_incomplete("bad renderbuffer stencil format");
854
            return;
855
         }
856
      }
857
   }
858
   else {
859
      ASSERT(att->Type == GL_NONE);
860
      /* complete */
861
      return;
862
   }
863
}
864
 
865
 
866
/**
867
 * Test if the given framebuffer object is complete and update its
868
 * Status field with the results.
869
 * Calls the ctx->Driver.ValidateFramebuffer() function to allow the
870
 * driver to make hardware-specific validation/completeness checks.
871
 * Also update the framebuffer's Width and Height fields if the
872
 * framebuffer is complete.
873
 */
874
void
875
_mesa_test_framebuffer_completeness(struct gl_context *ctx,
876
                                    struct gl_framebuffer *fb)
877
{
878
   GLuint numImages;
879
   GLenum intFormat = GL_NONE; /* color buffers' internal format */
880
   GLuint minWidth = ~0, minHeight = ~0, maxWidth = 0, maxHeight = 0;
881
   GLint numSamples = -1;
882
   GLint fixedSampleLocations = -1;
883
   GLint i;
884
   GLuint j;
885
   bool layer_count_valid = false;
886
   GLuint layer_count = 0, att_layer_count;
887
 
888
   assert(_mesa_is_user_fbo(fb));
889
 
890
   /* we're changing framebuffer fields here */
891
   FLUSH_VERTICES(ctx, _NEW_BUFFERS);
892
 
893
   numImages = 0;
894
   fb->Width = 0;
895
   fb->Height = 0;
896
   fb->_AllColorBuffersFixedPoint = GL_TRUE;
897
   fb->_HasSNormOrFloatColorBuffer = GL_FALSE;
898
 
899
   /* Start at -2 to more easily loop over all attachment points.
900
    *  -2: depth buffer
901
    *  -1: stencil buffer
902
    * >=0: color buffer
903
    */
904
   for (i = -2; i < (GLint) ctx->Const.MaxColorAttachments; i++) {
905
      struct gl_renderbuffer_attachment *att;
906
      GLenum f;
907
      gl_format attFormat;
908
 
909
      /*
910
       * XXX for ARB_fbo, only check color buffers that are named by
911
       * GL_READ_BUFFER and GL_DRAW_BUFFERi.
912
       */
913
 
914
      /* check for attachment completeness
915
       */
916
      if (i == -2) {
917
         att = &fb->Attachment[BUFFER_DEPTH];
918
         test_attachment_completeness(ctx, GL_DEPTH, att);
919
         if (!att->Complete) {
920
            fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT;
921
            fbo_incomplete(ctx, "depth attachment incomplete", -1);
922
            return;
923
         }
924
      }
925
      else if (i == -1) {
926
         att = &fb->Attachment[BUFFER_STENCIL];
927
         test_attachment_completeness(ctx, GL_STENCIL, att);
928
         if (!att->Complete) {
929
            fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT;
930
            fbo_incomplete(ctx, "stencil attachment incomplete", -1);
931
            return;
932
         }
933
      }
934
      else {
935
         att = &fb->Attachment[BUFFER_COLOR0 + i];
936
         test_attachment_completeness(ctx, GL_COLOR, att);
937
         if (!att->Complete) {
938
            fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT;
939
            fbo_incomplete(ctx, "color attachment incomplete", i);
940
            return;
941
         }
942
      }
943
 
944
      /* get width, height, format of the renderbuffer/texture
945
       */
946
      if (att->Type == GL_TEXTURE) {
947
         const struct gl_texture_image *texImg = att->Renderbuffer->TexImage;
948
         minWidth = MIN2(minWidth, texImg->Width);
949
         maxWidth = MAX2(maxWidth, texImg->Width);
950
         minHeight = MIN2(minHeight, texImg->Height);
951
         maxHeight = MAX2(maxHeight, texImg->Height);
952
         f = texImg->_BaseFormat;
953
         attFormat = texImg->TexFormat;
954
         numImages++;
955
 
956
         if (!is_format_color_renderable(ctx, attFormat, texImg->InternalFormat) &&
957
             !is_legal_depth_format(ctx, f)) {
958
            fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT;
959
            fbo_incomplete(ctx, "texture attachment incomplete", -1);
960
            return;
961
         }
962
 
963
         if (numSamples < 0)
964
            numSamples = texImg->NumSamples;
965
         else if (numSamples != texImg->NumSamples) {
966
            fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
967
            fbo_incomplete(ctx, "inconsistent sample count", -1);
968
            return;
969
         }
970
 
971
         if (fixedSampleLocations < 0)
972
            fixedSampleLocations = texImg->FixedSampleLocations;
973
         else if (fixedSampleLocations != texImg->FixedSampleLocations) {
974
            fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
975
            fbo_incomplete(ctx, "inconsistent fixed sample locations", -1);
976
            return;
977
         }
978
      }
979
      else if (att->Type == GL_RENDERBUFFER_EXT) {
980
         minWidth = MIN2(minWidth, att->Renderbuffer->Width);
981
         maxWidth = MAX2(minWidth, att->Renderbuffer->Width);
982
         minHeight = MIN2(minHeight, att->Renderbuffer->Height);
983
         maxHeight = MAX2(minHeight, att->Renderbuffer->Height);
984
         f = att->Renderbuffer->InternalFormat;
985
         attFormat = att->Renderbuffer->Format;
986
         numImages++;
987
 
988
         if (numSamples < 0)
989
            numSamples = att->Renderbuffer->NumSamples;
990
         else if (numSamples != att->Renderbuffer->NumSamples) {
991
            fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
992
            fbo_incomplete(ctx, "inconsistent sample count", -1);
993
            return;
994
         }
995
 
996
         /* RENDERBUFFER has fixedSampleLocations implicitly true */
997
         if (fixedSampleLocations < 0)
998
            fixedSampleLocations = GL_TRUE;
999
         else if (fixedSampleLocations != GL_TRUE) {
1000
            fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
1001
            fbo_incomplete(ctx, "inconsistent fixed sample locations", -1);
1002
            return;
1003
         }
1004
      }
1005
      else {
1006
         assert(att->Type == GL_NONE);
1007
         continue;
1008
      }
1009
 
1010
      /* check if integer color */
1011
      fb->_IntegerColor = _mesa_is_format_integer_color(attFormat);
1012
 
1013
      /* Update _AllColorBuffersFixedPoint and _HasSNormOrFloatColorBuffer. */
1014
      if (i >= 0) {
1015
         GLenum type = _mesa_get_format_datatype(attFormat);
1016
 
1017
         fb->_AllColorBuffersFixedPoint =
1018
            fb->_AllColorBuffersFixedPoint &&
1019
            (type == GL_UNSIGNED_NORMALIZED || type == GL_SIGNED_NORMALIZED);
1020
 
1021
         fb->_HasSNormOrFloatColorBuffer =
1022
            fb->_HasSNormOrFloatColorBuffer ||
1023
            type == GL_SIGNED_NORMALIZED || type == GL_FLOAT;
1024
      }
1025
 
1026
      /* Error-check width, height, format */
1027
      if (numImages == 1) {
1028
         /* save format */
1029
         if (i >= 0) {
1030
            intFormat = f;
1031
         }
1032
      }
1033
      else {
1034
         if (!ctx->Extensions.ARB_framebuffer_object) {
1035
            /* check that width, height, format are same */
1036
            if (minWidth != maxWidth || minHeight != maxHeight) {
1037
               fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT;
1038
               fbo_incomplete(ctx, "width or height mismatch", -1);
1039
               return;
1040
            }
1041
            /* check that all color buffers are the same format */
1042
            if (intFormat != GL_NONE && f != intFormat) {
1043
               fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT;
1044
               fbo_incomplete(ctx, "format mismatch", -1);
1045
               return;
1046
            }
1047
         }
1048
      }
1049
 
1050
      /* Check that the format is valid. (MESA_FORMAT_NONE means unsupported)
1051
       */
1052
      if (att->Type == GL_RENDERBUFFER &&
1053
          att->Renderbuffer->Format == MESA_FORMAT_NONE) {
1054
         fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED;
1055
         fbo_incomplete(ctx, "unsupported renderbuffer format", i);
1056
         return;
1057
      }
1058
 
1059
      /* Check that layered rendering is consistent. */
1060
      att_layer_count = att->Layered ? att->Renderbuffer->Depth : 0;
1061
      if (!layer_count_valid) {
1062
         layer_count = att_layer_count;
1063
         layer_count_valid = true;
1064
      } else if (layer_count != att_layer_count) {
1065
         if (layer_count == 0 || att_layer_count == 0) {
1066
            fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS;
1067
            fbo_incomplete(ctx, "framebuffer attachment layer mode is inconsistent", i);
1068
         } else {
1069
            fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_ARB;
1070
            fbo_incomplete(ctx, "framebuffer attachment layer count is inconsistent", i);
1071
         }
1072
         return;
1073
      }
1074
   }
1075
 
1076
   fb->Layered = layer_count > 0;
1077
 
1078
   if (_mesa_is_desktop_gl(ctx) && !ctx->Extensions.ARB_ES2_compatibility) {
1079
      /* Check that all DrawBuffers are present */
1080
      for (j = 0; j < ctx->Const.MaxDrawBuffers; j++) {
1081
	 if (fb->ColorDrawBuffer[j] != GL_NONE) {
1082
	    const struct gl_renderbuffer_attachment *att
1083
	       = _mesa_get_attachment(ctx, fb, fb->ColorDrawBuffer[j]);
1084
	    assert(att);
1085
	    if (att->Type == GL_NONE) {
1086
	       fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT;
1087
	       fbo_incomplete(ctx, "missing drawbuffer", j);
1088
	       return;
1089
	    }
1090
	 }
1091
      }
1092
 
1093
      /* Check that the ReadBuffer is present */
1094
      if (fb->ColorReadBuffer != GL_NONE) {
1095
	 const struct gl_renderbuffer_attachment *att
1096
	    = _mesa_get_attachment(ctx, fb, fb->ColorReadBuffer);
1097
	 assert(att);
1098
	 if (att->Type == GL_NONE) {
1099
	    fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT;
1100
            fbo_incomplete(ctx, "missing readbuffer", -1);
1101
	    return;
1102
	 }
1103
      }
1104
   }
1105
 
1106
   if (numImages == 0) {
1107
      fb->_Status = GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT;
1108
      fbo_incomplete(ctx, "no attachments", -1);
1109
      return;
1110
   }
1111
 
1112
   /* Provisionally set status = COMPLETE ... */
1113
   fb->_Status = GL_FRAMEBUFFER_COMPLETE_EXT;
1114
 
1115
   /* ... but the driver may say the FB is incomplete.
1116
    * Drivers will most likely set the status to GL_FRAMEBUFFER_UNSUPPORTED
1117
    * if anything.
1118
    */
1119
   if (ctx->Driver.ValidateFramebuffer) {
1120
      ctx->Driver.ValidateFramebuffer(ctx, fb);
1121
      if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
1122
         fbo_incomplete(ctx, "driver marked FBO as incomplete", -1);
1123
      }
1124
   }
1125
 
1126
   if (fb->_Status == GL_FRAMEBUFFER_COMPLETE_EXT) {
1127
      /*
1128
       * Note that if ARB_framebuffer_object is supported and the attached
1129
       * renderbuffers/textures are different sizes, the framebuffer
1130
       * width/height will be set to the smallest width/height.
1131
       */
1132
      fb->Width = minWidth;
1133
      fb->Height = minHeight;
1134
 
1135
      /* finally, update the visual info for the framebuffer */
1136
      _mesa_update_framebuffer_visual(ctx, fb);
1137
   }
1138
}
1139
 
1140
 
1141
GLboolean GLAPIENTRY
1142
_mesa_IsRenderbuffer(GLuint renderbuffer)
1143
{
1144
   GET_CURRENT_CONTEXT(ctx);
1145
   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
1146
   if (renderbuffer) {
1147
      struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
1148
      if (rb != NULL && rb != &DummyRenderbuffer)
1149
         return GL_TRUE;
1150
   }
1151
   return GL_FALSE;
1152
}
1153
 
1154
 
1155
static void
1156
bind_renderbuffer(GLenum target, GLuint renderbuffer, bool allow_user_names)
1157
{
1158
   struct gl_renderbuffer *newRb;
1159
   GET_CURRENT_CONTEXT(ctx);
1160
 
1161
   if (target != GL_RENDERBUFFER_EXT) {
1162
      _mesa_error(ctx, GL_INVALID_ENUM, "glBindRenderbufferEXT(target)");
1163
      return;
1164
   }
1165
 
1166
   /* No need to flush here since the render buffer binding has no
1167
    * effect on rendering state.
1168
    */
1169
 
1170
   if (renderbuffer) {
1171
      newRb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
1172
      if (newRb == &DummyRenderbuffer) {
1173
         /* ID was reserved, but no real renderbuffer object made yet */
1174
         newRb = NULL;
1175
      }
1176
      else if (!newRb && !allow_user_names) {
1177
         /* All RB IDs must be Gen'd */
1178
         _mesa_error(ctx, GL_INVALID_OPERATION, "glBindRenderbuffer(buffer)");
1179
         return;
1180
      }
1181
 
1182
      if (!newRb) {
1183
	 /* create new renderbuffer object */
1184
	 newRb = ctx->Driver.NewRenderbuffer(ctx, renderbuffer);
1185
	 if (!newRb) {
1186
	    _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindRenderbufferEXT");
1187
	    return;
1188
	 }
1189
         ASSERT(newRb->AllocStorage);
1190
         _mesa_HashInsert(ctx->Shared->RenderBuffers, renderbuffer, newRb);
1191
         newRb->RefCount = 1; /* referenced by hash table */
1192
      }
1193
   }
1194
   else {
1195
      newRb = NULL;
1196
   }
1197
 
1198
   ASSERT(newRb != &DummyRenderbuffer);
1199
 
1200
   _mesa_reference_renderbuffer(&ctx->CurrentRenderbuffer, newRb);
1201
}
1202
 
1203
void GLAPIENTRY
1204
_mesa_BindRenderbuffer(GLenum target, GLuint renderbuffer)
1205
{
1206
   GET_CURRENT_CONTEXT(ctx);
1207
 
1208
   /* OpenGL ES glBindRenderbuffer and glBindRenderbufferOES use this same
1209
    * entry point, but they allow the use of user-generated names.
1210
    */
1211
   bind_renderbuffer(target, renderbuffer, _mesa_is_gles(ctx));
1212
}
1213
 
1214
void GLAPIENTRY
1215
_mesa_BindRenderbufferEXT(GLenum target, GLuint renderbuffer)
1216
{
1217
   /* This function should not be in the dispatch table for core profile /
1218
    * OpenGL 3.1, so execution should never get here in those cases -- no
1219
    * need for an explicit test.
1220
    */
1221
   bind_renderbuffer(target, renderbuffer, true);
1222
}
1223
 
1224
 
1225
/**
1226
 * Remove the specified renderbuffer or texture from any attachment point in
1227
 * the framebuffer.
1228
 *
1229
 * \returns
1230
 * \c true if the renderbuffer was detached from an attachment point.  \c
1231
 * false otherwise.
1232
 */
1233
bool
1234
_mesa_detach_renderbuffer(struct gl_context *ctx,
1235
                          struct gl_framebuffer *fb,
1236
                          const void *att)
1237
{
1238
   unsigned i;
1239
   bool progress = false;
1240
 
1241
   for (i = 0; i < BUFFER_COUNT; i++) {
1242
      if (fb->Attachment[i].Texture == att
1243
          || fb->Attachment[i].Renderbuffer == att) {
1244
         _mesa_remove_attachment(ctx, &fb->Attachment[i]);
1245
         progress = true;
1246
      }
1247
   }
1248
 
1249
   /* Section 4.4.4 (Framebuffer Completeness), subsection "Whole Framebuffer
1250
    * Completeness," of the OpenGL 3.1 spec says:
1251
    *
1252
    *     "Performing any of the following actions may change whether the
1253
    *     framebuffer is considered complete or incomplete:
1254
    *
1255
    *     ...
1256
    *
1257
    *        - Deleting, with DeleteTextures or DeleteRenderbuffers, an object
1258
    *          containing an image that is attached to a framebuffer object
1259
    *          that is bound to the framebuffer."
1260
    */
1261
   if (progress)
1262
      invalidate_framebuffer(fb);
1263
 
1264
   return progress;
1265
}
1266
 
1267
 
1268
void GLAPIENTRY
1269
_mesa_DeleteRenderbuffers(GLsizei n, const GLuint *renderbuffers)
1270
{
1271
   GLint i;
1272
   GET_CURRENT_CONTEXT(ctx);
1273
 
1274
   FLUSH_VERTICES(ctx, _NEW_BUFFERS);
1275
 
1276
   for (i = 0; i < n; i++) {
1277
      if (renderbuffers[i] > 0) {
1278
	 struct gl_renderbuffer *rb;
1279
	 rb = _mesa_lookup_renderbuffer(ctx, renderbuffers[i]);
1280
	 if (rb) {
1281
            /* check if deleting currently bound renderbuffer object */
1282
            if (rb == ctx->CurrentRenderbuffer) {
1283
               /* bind default */
1284
               ASSERT(rb->RefCount >= 2);
1285
               _mesa_BindRenderbuffer(GL_RENDERBUFFER_EXT, 0);
1286
            }
1287
 
1288
            /* Section 4.4.2 (Attaching Images to Framebuffer Objects),
1289
             * subsection "Attaching Renderbuffer Images to a Framebuffer," of
1290
             * the OpenGL 3.1 spec says:
1291
             *
1292
             *     "If a renderbuffer object is deleted while its image is
1293
             *     attached to one or more attachment points in the currently
1294
             *     bound framebuffer, then it is as if FramebufferRenderbuffer
1295
             *     had been called, with a renderbuffer of 0, for each
1296
             *     attachment point to which this image was attached in the
1297
             *     currently bound framebuffer. In other words, this
1298
             *     renderbuffer image is first detached from all attachment
1299
             *     points in the currently bound framebuffer. Note that the
1300
             *     renderbuffer image is specifically not detached from any
1301
             *     non-bound framebuffers. Detaching the image from any
1302
             *     non-bound framebuffers is the responsibility of the
1303
             *     application.
1304
             */
1305
            if (_mesa_is_user_fbo(ctx->DrawBuffer)) {
1306
               _mesa_detach_renderbuffer(ctx, ctx->DrawBuffer, rb);
1307
            }
1308
            if (_mesa_is_user_fbo(ctx->ReadBuffer)
1309
                && ctx->ReadBuffer != ctx->DrawBuffer) {
1310
               _mesa_detach_renderbuffer(ctx, ctx->ReadBuffer, rb);
1311
            }
1312
 
1313
	    /* Remove from hash table immediately, to free the ID.
1314
             * But the object will not be freed until it's no longer
1315
             * referenced anywhere else.
1316
             */
1317
	    _mesa_HashRemove(ctx->Shared->RenderBuffers, renderbuffers[i]);
1318
 
1319
            if (rb != &DummyRenderbuffer) {
1320
               /* no longer referenced by hash table */
1321
               _mesa_reference_renderbuffer(&rb, NULL);
1322
	    }
1323
	 }
1324
      }
1325
   }
1326
}
1327
 
1328
 
1329
void GLAPIENTRY
1330
_mesa_GenRenderbuffers(GLsizei n, GLuint *renderbuffers)
1331
{
1332
   GET_CURRENT_CONTEXT(ctx);
1333
   GLuint first;
1334
   GLint i;
1335
 
1336
   if (n < 0) {
1337
      _mesa_error(ctx, GL_INVALID_VALUE, "glGenRenderbuffersEXT(n)");
1338
      return;
1339
   }
1340
 
1341
   if (!renderbuffers)
1342
      return;
1343
 
1344
   first = _mesa_HashFindFreeKeyBlock(ctx->Shared->RenderBuffers, n);
1345
 
1346
   for (i = 0; i < n; i++) {
1347
      GLuint name = first + i;
1348
      renderbuffers[i] = name;
1349
      /* insert dummy placeholder into hash table */
1350
      _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
1351
      _mesa_HashInsert(ctx->Shared->RenderBuffers, name, &DummyRenderbuffer);
1352
      _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
1353
   }
1354
}
1355
 
1356
 
1357
/**
1358
 * Given an internal format token for a render buffer, return the
1359
 * corresponding base format (one of GL_RGB, GL_RGBA, GL_STENCIL_INDEX,
1360
 * GL_DEPTH_COMPONENT, GL_DEPTH_STENCIL_EXT, GL_ALPHA, GL_LUMINANCE,
1361
 * GL_LUMINANCE_ALPHA, GL_INTENSITY, etc).
1362
 *
1363
 * This is similar to _mesa_base_tex_format() but the set of valid
1364
 * internal formats is different.
1365
 *
1366
 * Note that even if a format is determined to be legal here, validation
1367
 * of the FBO may fail if the format is not supported by the driver/GPU.
1368
 *
1369
 * \param internalFormat  as passed to glRenderbufferStorage()
1370
 * \return the base internal format, or 0 if internalFormat is illegal
1371
 */
1372
GLenum
1373
_mesa_base_fbo_format(struct gl_context *ctx, GLenum internalFormat)
1374
{
1375
   /*
1376
    * Notes: some formats such as alpha, luminance, etc. were added
1377
    * with GL_ARB_framebuffer_object.
1378
    */
1379
   switch (internalFormat) {
1380
   case GL_ALPHA:
1381
   case GL_ALPHA4:
1382
   case GL_ALPHA8:
1383
   case GL_ALPHA12:
1384
   case GL_ALPHA16:
1385
      return ctx->API == API_OPENGL_COMPAT && ctx->Extensions.ARB_framebuffer_object
1386
         ? GL_ALPHA : 0;
1387
   case GL_LUMINANCE:
1388
   case GL_LUMINANCE4:
1389
   case GL_LUMINANCE8:
1390
   case GL_LUMINANCE12:
1391
   case GL_LUMINANCE16:
1392
      return ctx->API == API_OPENGL_COMPAT && ctx->Extensions.ARB_framebuffer_object
1393
         ? GL_LUMINANCE : 0;
1394
   case GL_LUMINANCE_ALPHA:
1395
   case GL_LUMINANCE4_ALPHA4:
1396
   case GL_LUMINANCE6_ALPHA2:
1397
   case GL_LUMINANCE8_ALPHA8:
1398
   case GL_LUMINANCE12_ALPHA4:
1399
   case GL_LUMINANCE12_ALPHA12:
1400
   case GL_LUMINANCE16_ALPHA16:
1401
      return ctx->API == API_OPENGL_COMPAT && ctx->Extensions.ARB_framebuffer_object
1402
         ? GL_LUMINANCE_ALPHA : 0;
1403
   case GL_INTENSITY:
1404
   case GL_INTENSITY4:
1405
   case GL_INTENSITY8:
1406
   case GL_INTENSITY12:
1407
   case GL_INTENSITY16:
1408
      return ctx->API == API_OPENGL_COMPAT && ctx->Extensions.ARB_framebuffer_object
1409
         ? GL_INTENSITY : 0;
1410
   case GL_RGB8:
1411
      return GL_RGB;
1412
   case GL_RGB:
1413
   case GL_R3_G3_B2:
1414
   case GL_RGB4:
1415
   case GL_RGB5:
1416
   case GL_RGB10:
1417
   case GL_RGB12:
1418
   case GL_RGB16:
1419
      return _mesa_is_desktop_gl(ctx) ? GL_RGB : 0;
1420
   case GL_SRGB8_EXT:
1421
      return _mesa_is_desktop_gl(ctx) ? GL_RGB : 0;
1422
   case GL_RGBA4:
1423
   case GL_RGB5_A1:
1424
   case GL_RGBA8:
1425
      return GL_RGBA;
1426
   case GL_RGBA:
1427
   case GL_RGBA2:
1428
   case GL_RGBA12:
1429
   case GL_RGBA16:
1430
      return _mesa_is_desktop_gl(ctx) ? GL_RGBA : 0;
1431
   case GL_RGB10_A2:
1432
   case GL_SRGB8_ALPHA8_EXT:
1433
      return _mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx) ? GL_RGBA : 0;
1434
   case GL_STENCIL_INDEX:
1435
   case GL_STENCIL_INDEX1_EXT:
1436
   case GL_STENCIL_INDEX4_EXT:
1437
   case GL_STENCIL_INDEX16_EXT:
1438
      /* There are extensions for GL_STENCIL_INDEX1 and GL_STENCIL_INDEX4 in
1439
       * OpenGL ES, but Mesa does not currently support them.
1440
       */
1441
      return _mesa_is_desktop_gl(ctx) ? GL_STENCIL_INDEX : 0;
1442
   case GL_STENCIL_INDEX8_EXT:
1443
      return GL_STENCIL_INDEX;
1444
   case GL_DEPTH_COMPONENT:
1445
   case GL_DEPTH_COMPONENT32:
1446
      return _mesa_is_desktop_gl(ctx) ? GL_DEPTH_COMPONENT : 0;
1447
   case GL_DEPTH_COMPONENT16:
1448
   case GL_DEPTH_COMPONENT24:
1449
      return GL_DEPTH_COMPONENT;
1450
   case GL_DEPTH_STENCIL_EXT:
1451
      return _mesa_is_desktop_gl(ctx)
1452
         && ctx->Extensions.EXT_packed_depth_stencil
1453
         ? GL_DEPTH_STENCIL_EXT : 0;
1454
   case GL_DEPTH24_STENCIL8_EXT:
1455
      return ctx->Extensions.EXT_packed_depth_stencil
1456
         ? GL_DEPTH_STENCIL_EXT : 0;
1457
   case GL_DEPTH_COMPONENT32F:
1458
      return ctx->Version >= 30
1459
         || (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.ARB_depth_buffer_float)
1460
         ? GL_DEPTH_COMPONENT : 0;
1461
   case GL_DEPTH32F_STENCIL8:
1462
      return ctx->Version >= 30
1463
         || (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.ARB_depth_buffer_float)
1464
         ? GL_DEPTH_STENCIL : 0;
1465
   case GL_RED:
1466
   case GL_R16:
1467
      return _mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_texture_rg
1468
         ? GL_RED : 0;
1469
   case GL_R8:
1470
      return ctx->API != API_OPENGLES && ctx->Extensions.ARB_texture_rg
1471
         ? GL_RED : 0;
1472
   case GL_RG:
1473
   case GL_RG16:
1474
      return _mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_texture_rg
1475
         ? GL_RG : 0;
1476
   case GL_RG8:
1477
      return ctx->API != API_OPENGLES && ctx->Extensions.ARB_texture_rg
1478
         ? GL_RG : 0;
1479
   /* signed normalized texture formats */
1480
   case GL_RED_SNORM:
1481
   case GL_R8_SNORM:
1482
   case GL_R16_SNORM:
1483
      return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_snorm
1484
         ? GL_RED : 0;
1485
   case GL_RG_SNORM:
1486
   case GL_RG8_SNORM:
1487
   case GL_RG16_SNORM:
1488
      return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_snorm
1489
         ? GL_RG : 0;
1490
   case GL_RGB_SNORM:
1491
   case GL_RGB8_SNORM:
1492
   case GL_RGB16_SNORM:
1493
      return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_snorm
1494
         ? GL_RGB : 0;
1495
   case GL_RGBA_SNORM:
1496
   case GL_RGBA8_SNORM:
1497
   case GL_RGBA16_SNORM:
1498
      return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_snorm
1499
         ? GL_RGBA : 0;
1500
   case GL_ALPHA_SNORM:
1501
   case GL_ALPHA8_SNORM:
1502
   case GL_ALPHA16_SNORM:
1503
      return ctx->API == API_OPENGL_COMPAT &&
1504
             ctx->Extensions.EXT_texture_snorm &&
1505
             ctx->Extensions.ARB_framebuffer_object ? GL_ALPHA : 0;
1506
   case GL_R16F:
1507
   case GL_R32F:
1508
      return ((_mesa_is_desktop_gl(ctx) &&
1509
               ctx->Extensions.ARB_texture_rg &&
1510
               ctx->Extensions.ARB_texture_float) ||
1511
              _mesa_is_gles3(ctx) /* EXT_color_buffer_float */ )
1512
         ? GL_RED : 0;
1513
   case GL_RG16F:
1514
   case GL_RG32F:
1515
      return ((_mesa_is_desktop_gl(ctx) &&
1516
               ctx->Extensions.ARB_texture_rg &&
1517
               ctx->Extensions.ARB_texture_float) ||
1518
              _mesa_is_gles3(ctx) /* EXT_color_buffer_float */ )
1519
         ? GL_RG : 0;
1520
   case GL_RGB16F:
1521
   case GL_RGB32F:
1522
      return (_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_texture_float)
1523
         ? GL_RGB : 0;
1524
   case GL_RGBA16F:
1525
   case GL_RGBA32F:
1526
      return ((_mesa_is_desktop_gl(ctx) &&
1527
               ctx->Extensions.ARB_texture_float) ||
1528
              _mesa_is_gles3(ctx) /* EXT_color_buffer_float */ )
1529
         ? GL_RGBA : 0;
1530
   case GL_ALPHA16F_ARB:
1531
   case GL_ALPHA32F_ARB:
1532
      return ctx->API == API_OPENGL_COMPAT &&
1533
             ctx->Extensions.ARB_texture_float &&
1534
             ctx->Extensions.ARB_framebuffer_object ? GL_ALPHA : 0;
1535
   case GL_LUMINANCE16F_ARB:
1536
   case GL_LUMINANCE32F_ARB:
1537
      return ctx->API == API_OPENGL_COMPAT &&
1538
             ctx->Extensions.ARB_texture_float &&
1539
             ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE : 0;
1540
   case GL_LUMINANCE_ALPHA16F_ARB:
1541
   case GL_LUMINANCE_ALPHA32F_ARB:
1542
      return ctx->API == API_OPENGL_COMPAT &&
1543
             ctx->Extensions.ARB_texture_float &&
1544
             ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE_ALPHA : 0;
1545
   case GL_INTENSITY16F_ARB:
1546
   case GL_INTENSITY32F_ARB:
1547
      return ctx->API == API_OPENGL_COMPAT &&
1548
             ctx->Extensions.ARB_texture_float &&
1549
             ctx->Extensions.ARB_framebuffer_object ? GL_INTENSITY : 0;
1550
   case GL_RGB9_E5:
1551
      return (_mesa_is_desktop_gl(ctx)
1552
              && ctx->Extensions.EXT_texture_shared_exponent)
1553
         ? GL_RGB : 0;
1554
   case GL_R11F_G11F_B10F:
1555
      return ((_mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_packed_float) ||
1556
              _mesa_is_gles3(ctx) /* EXT_color_buffer_float */ )
1557
         ? GL_RGB : 0;
1558
 
1559
   case GL_RGBA8UI_EXT:
1560
   case GL_RGBA16UI_EXT:
1561
   case GL_RGBA32UI_EXT:
1562
   case GL_RGBA8I_EXT:
1563
   case GL_RGBA16I_EXT:
1564
   case GL_RGBA32I_EXT:
1565
      return ctx->Version >= 30
1566
         || (_mesa_is_desktop_gl(ctx) &&
1567
             ctx->Extensions.EXT_texture_integer) ? GL_RGBA : 0;
1568
 
1569
   case GL_RGB8UI_EXT:
1570
   case GL_RGB16UI_EXT:
1571
   case GL_RGB32UI_EXT:
1572
   case GL_RGB8I_EXT:
1573
   case GL_RGB16I_EXT:
1574
   case GL_RGB32I_EXT:
1575
      return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_integer
1576
         ? GL_RGB : 0;
1577
   case GL_R8UI:
1578
   case GL_R8I:
1579
   case GL_R16UI:
1580
   case GL_R16I:
1581
   case GL_R32UI:
1582
   case GL_R32I:
1583
      return ctx->Version >= 30
1584
         || (_mesa_is_desktop_gl(ctx) &&
1585
             ctx->Extensions.ARB_texture_rg &&
1586
             ctx->Extensions.EXT_texture_integer) ? GL_RED : 0;
1587
 
1588
   case GL_RG8UI:
1589
   case GL_RG8I:
1590
   case GL_RG16UI:
1591
   case GL_RG16I:
1592
   case GL_RG32UI:
1593
   case GL_RG32I:
1594
      return ctx->Version >= 30
1595
         || (_mesa_is_desktop_gl(ctx) &&
1596
             ctx->Extensions.ARB_texture_rg &&
1597
             ctx->Extensions.EXT_texture_integer) ? GL_RG : 0;
1598
 
1599
   case GL_INTENSITY8I_EXT:
1600
   case GL_INTENSITY8UI_EXT:
1601
   case GL_INTENSITY16I_EXT:
1602
   case GL_INTENSITY16UI_EXT:
1603
   case GL_INTENSITY32I_EXT:
1604
   case GL_INTENSITY32UI_EXT:
1605
      return ctx->API == API_OPENGL_COMPAT &&
1606
             ctx->Extensions.EXT_texture_integer &&
1607
             ctx->Extensions.ARB_framebuffer_object ? GL_INTENSITY : 0;
1608
 
1609
   case GL_LUMINANCE8I_EXT:
1610
   case GL_LUMINANCE8UI_EXT:
1611
   case GL_LUMINANCE16I_EXT:
1612
   case GL_LUMINANCE16UI_EXT:
1613
   case GL_LUMINANCE32I_EXT:
1614
   case GL_LUMINANCE32UI_EXT:
1615
      return ctx->API == API_OPENGL_COMPAT &&
1616
             ctx->Extensions.EXT_texture_integer &&
1617
             ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE : 0;
1618
 
1619
   case GL_LUMINANCE_ALPHA8I_EXT:
1620
   case GL_LUMINANCE_ALPHA8UI_EXT:
1621
   case GL_LUMINANCE_ALPHA16I_EXT:
1622
   case GL_LUMINANCE_ALPHA16UI_EXT:
1623
   case GL_LUMINANCE_ALPHA32I_EXT:
1624
   case GL_LUMINANCE_ALPHA32UI_EXT:
1625
      return ctx->API == API_OPENGL_COMPAT &&
1626
             ctx->Extensions.EXT_texture_integer &&
1627
             ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE_ALPHA : 0;
1628
 
1629
   case GL_ALPHA8I_EXT:
1630
   case GL_ALPHA8UI_EXT:
1631
   case GL_ALPHA16I_EXT:
1632
   case GL_ALPHA16UI_EXT:
1633
   case GL_ALPHA32I_EXT:
1634
   case GL_ALPHA32UI_EXT:
1635
      return ctx->API == API_OPENGL_COMPAT &&
1636
             ctx->Extensions.EXT_texture_integer &&
1637
             ctx->Extensions.ARB_framebuffer_object ? GL_ALPHA : 0;
1638
 
1639
   case GL_RGB10_A2UI:
1640
      return (_mesa_is_desktop_gl(ctx) &&
1641
              ctx->Extensions.ARB_texture_rgb10_a2ui)
1642
         || _mesa_is_gles3(ctx) ? GL_RGBA : 0;
1643
 
1644
   case GL_RGB565:
1645
      return _mesa_is_gles(ctx) || ctx->Extensions.ARB_ES2_compatibility
1646
         ? GL_RGB : 0;
1647
   default:
1648
      return 0;
1649
   }
1650
}
1651
 
1652
 
1653
/**
1654
 * Invalidate a renderbuffer attachment.  Called from _mesa_HashWalk().
1655
 */
1656
static void
1657
invalidate_rb(GLuint key, void *data, void *userData)
1658
{
1659
   struct gl_framebuffer *fb = (struct gl_framebuffer *) data;
1660
   struct gl_renderbuffer *rb = (struct gl_renderbuffer *) userData;
1661
 
1662
   /* If this is a user-created FBO */
1663
   if (_mesa_is_user_fbo(fb)) {
1664
      GLuint i;
1665
      for (i = 0; i < BUFFER_COUNT; i++) {
1666
         struct gl_renderbuffer_attachment *att = fb->Attachment + i;
1667
         if (att->Type == GL_RENDERBUFFER &&
1668
             att->Renderbuffer == rb) {
1669
            /* Mark fb status as indeterminate to force re-validation */
1670
            fb->_Status = 0;
1671
            return;
1672
         }
1673
      }
1674
   }
1675
}
1676
 
1677
 
1678
/** sentinal value, see below */
1679
#define NO_SAMPLES 1000
1680
 
1681
 
1682
/**
1683
 * Helper function used by _mesa_RenderbufferStorage() and
1684
 * _mesa_RenderbufferStorageMultisample().
1685
 * samples will be NO_SAMPLES if called by _mesa_RenderbufferStorage().
1686
 */
1687
static void
1688
renderbuffer_storage(GLenum target, GLenum internalFormat,
1689
                     GLsizei width, GLsizei height, GLsizei samples)
1690
{
1691
   const char *func = samples == NO_SAMPLES ?
1692
      "glRenderbufferStorage" : "glRenderbufferStorageMultisample";
1693
   struct gl_renderbuffer *rb;
1694
   GLenum baseFormat;
1695
   GLenum sample_count_error;
1696
   GET_CURRENT_CONTEXT(ctx);
1697
 
1698
   if (MESA_VERBOSE & VERBOSE_API) {
1699
      if (samples == NO_SAMPLES)
1700
         _mesa_debug(ctx, "%s(%s, %s, %d, %d)\n",
1701
                     func,
1702
                     _mesa_lookup_enum_by_nr(target),
1703
                     _mesa_lookup_enum_by_nr(internalFormat),
1704
                     width, height);
1705
      else
1706
         _mesa_debug(ctx, "%s(%s, %s, %d, %d, %d)\n",
1707
                     func,
1708
                     _mesa_lookup_enum_by_nr(target),
1709
                     _mesa_lookup_enum_by_nr(internalFormat),
1710
                     width, height, samples);
1711
   }
1712
 
1713
   if (target != GL_RENDERBUFFER_EXT) {
1714
      _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", func);
1715
      return;
1716
   }
1717
 
1718
   baseFormat = _mesa_base_fbo_format(ctx, internalFormat);
1719
   if (baseFormat == 0) {
1720
      _mesa_error(ctx, GL_INVALID_ENUM, "%s(internalFormat=%s)",
1721
                  func, _mesa_lookup_enum_by_nr(internalFormat));
1722
      return;
1723
   }
1724
 
1725
   if (width < 0 || width > (GLsizei) ctx->Const.MaxRenderbufferSize) {
1726
      _mesa_error(ctx, GL_INVALID_VALUE, "%s(width)", func);
1727
      return;
1728
   }
1729
 
1730
   if (height < 0 || height > (GLsizei) ctx->Const.MaxRenderbufferSize) {
1731
      _mesa_error(ctx, GL_INVALID_VALUE, "%s(height)", func);
1732
      return;
1733
   }
1734
 
1735
   if (samples == NO_SAMPLES) {
1736
      /* NumSamples == 0 indicates non-multisampling */
1737
      samples = 0;
1738
   }
1739
   else {
1740
      /* check the sample count;
1741
       * note: driver may choose to use more samples than what's requested
1742
       */
1743
      sample_count_error = _mesa_check_sample_count(ctx, target,
1744
            internalFormat, samples);
1745
      if (sample_count_error != GL_NO_ERROR) {
1746
         _mesa_error(ctx, sample_count_error, "%s(samples)", func);
1747
         return;
1748
      }
1749
   }
1750
 
1751
   rb = ctx->CurrentRenderbuffer;
1752
   if (!rb) {
1753
      _mesa_error(ctx, GL_INVALID_OPERATION, "%s", func);
1754
      return;
1755
   }
1756
 
1757
   FLUSH_VERTICES(ctx, _NEW_BUFFERS);
1758
 
1759
   if (rb->InternalFormat == internalFormat &&
1760
       rb->Width == (GLuint) width &&
1761
       rb->Height == (GLuint) height &&
1762
       rb->NumSamples == samples) {
1763
      /* no change in allocation needed */
1764
      return;
1765
   }
1766
 
1767
   /* These MUST get set by the AllocStorage func */
1768
   rb->Format = MESA_FORMAT_NONE;
1769
   rb->NumSamples = samples;
1770
 
1771
   /* Now allocate the storage */
1772
   ASSERT(rb->AllocStorage);
1773
   if (rb->AllocStorage(ctx, rb, internalFormat, width, height)) {
1774
      /* No error - check/set fields now */
1775
      /* If rb->Format == MESA_FORMAT_NONE, the format is unsupported. */
1776
      assert(rb->Width == (GLuint) width);
1777
      assert(rb->Height == (GLuint) height);
1778
      rb->InternalFormat = internalFormat;
1779
      rb->_BaseFormat = baseFormat;
1780
      assert(rb->_BaseFormat != 0);
1781
   }
1782
   else {
1783
      /* Probably ran out of memory - clear the fields */
1784
      rb->Width = 0;
1785
      rb->Height = 0;
1786
      rb->Format = MESA_FORMAT_NONE;
1787
      rb->InternalFormat = GL_NONE;
1788
      rb->_BaseFormat = GL_NONE;
1789
      rb->NumSamples = 0;
1790
   }
1791
 
1792
   /* Invalidate the framebuffers the renderbuffer is attached in. */
1793
   if (rb->AttachedAnytime) {
1794
      _mesa_HashWalk(ctx->Shared->FrameBuffers, invalidate_rb, rb);
1795
   }
1796
}
1797
 
1798
 
1799
void GLAPIENTRY
1800
_mesa_EGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image)
1801
{
1802
   struct gl_renderbuffer *rb;
1803
   GET_CURRENT_CONTEXT(ctx);
1804
 
1805
   if (!ctx->Extensions.OES_EGL_image) {
1806
      _mesa_error(ctx, GL_INVALID_OPERATION,
1807
                  "glEGLImageTargetRenderbufferStorageOES(unsupported)");
1808
      return;
1809
   }
1810
 
1811
   if (target != GL_RENDERBUFFER) {
1812
      _mesa_error(ctx, GL_INVALID_ENUM,
1813
                  "EGLImageTargetRenderbufferStorageOES");
1814
      return;
1815
   }
1816
 
1817
   rb = ctx->CurrentRenderbuffer;
1818
   if (!rb) {
1819
      _mesa_error(ctx, GL_INVALID_OPERATION,
1820
                  "EGLImageTargetRenderbufferStorageOES");
1821
      return;
1822
   }
1823
 
1824
   FLUSH_VERTICES(ctx, _NEW_BUFFERS);
1825
 
1826
   ctx->Driver.EGLImageTargetRenderbufferStorage(ctx, rb, image);
1827
}
1828
 
1829
 
1830
/**
1831
 * Helper function for _mesa_GetRenderbufferParameteriv() and
1832
 * _mesa_GetFramebufferAttachmentParameteriv()
1833
 * We have to be careful to respect the base format.  For example, if a
1834
 * renderbuffer/texture was created with internalFormat=GL_RGB but the
1835
 * driver actually chose a GL_RGBA format, when the user queries ALPHA_SIZE
1836
 * we need to return zero.
1837
 */
1838
static GLint
1839
get_component_bits(GLenum pname, GLenum baseFormat, gl_format format)
1840
{
1841
   if (_mesa_base_format_has_channel(baseFormat, pname))
1842
      return _mesa_get_format_bits(format, pname);
1843
   else
1844
      return 0;
1845
}
1846
 
1847
 
1848
 
1849
void GLAPIENTRY
1850
_mesa_RenderbufferStorage(GLenum target, GLenum internalFormat,
1851
                             GLsizei width, GLsizei height)
1852
{
1853
   /* GL_ARB_fbo says calling this function is equivalent to calling
1854
    * glRenderbufferStorageMultisample() with samples=0.  We pass in
1855
    * a token value here just for error reporting purposes.
1856
    */
1857
   renderbuffer_storage(target, internalFormat, width, height, NO_SAMPLES);
1858
}
1859
 
1860
 
1861
void GLAPIENTRY
1862
_mesa_RenderbufferStorageMultisample(GLenum target, GLsizei samples,
1863
                                     GLenum internalFormat,
1864
                                     GLsizei width, GLsizei height)
1865
{
1866
   renderbuffer_storage(target, internalFormat, width, height, samples);
1867
}
1868
 
1869
 
1870
/**
1871
 * OpenGL ES version of glRenderBufferStorage.
1872
 */
1873
void GLAPIENTRY
1874
_es_RenderbufferStorageEXT(GLenum target, GLenum internalFormat,
1875
			   GLsizei width, GLsizei height)
1876
{
1877
   switch (internalFormat) {
1878
   case GL_RGB565:
1879
      /* XXX this confuses GL_RENDERBUFFER_INTERNAL_FORMAT_OES */
1880
      /* choose a closest format */
1881
      internalFormat = GL_RGB5;
1882
      break;
1883
   default:
1884
      break;
1885
   }
1886
 
1887
   renderbuffer_storage(target, internalFormat, width, height, 0);
1888
}
1889
 
1890
 
1891
void GLAPIENTRY
1892
_mesa_GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint *params)
1893
{
1894
   struct gl_renderbuffer *rb;
1895
   GET_CURRENT_CONTEXT(ctx);
1896
 
1897
   if (target != GL_RENDERBUFFER_EXT) {
1898
      _mesa_error(ctx, GL_INVALID_ENUM,
1899
                  "glGetRenderbufferParameterivEXT(target)");
1900
      return;
1901
   }
1902
 
1903
   rb = ctx->CurrentRenderbuffer;
1904
   if (!rb) {
1905
      _mesa_error(ctx, GL_INVALID_OPERATION,
1906
                  "glGetRenderbufferParameterivEXT");
1907
      return;
1908
   }
1909
 
1910
   /* No need to flush here since we're just quering state which is
1911
    * not effected by rendering.
1912
    */
1913
 
1914
   switch (pname) {
1915
   case GL_RENDERBUFFER_WIDTH_EXT:
1916
      *params = rb->Width;
1917
      return;
1918
   case GL_RENDERBUFFER_HEIGHT_EXT:
1919
      *params = rb->Height;
1920
      return;
1921
   case GL_RENDERBUFFER_INTERNAL_FORMAT_EXT:
1922
      *params = rb->InternalFormat;
1923
      return;
1924
   case GL_RENDERBUFFER_RED_SIZE_EXT:
1925
   case GL_RENDERBUFFER_GREEN_SIZE_EXT:
1926
   case GL_RENDERBUFFER_BLUE_SIZE_EXT:
1927
   case GL_RENDERBUFFER_ALPHA_SIZE_EXT:
1928
   case GL_RENDERBUFFER_DEPTH_SIZE_EXT:
1929
   case GL_RENDERBUFFER_STENCIL_SIZE_EXT:
1930
      *params = get_component_bits(pname, rb->_BaseFormat, rb->Format);
1931
      break;
1932
   case GL_RENDERBUFFER_SAMPLES:
1933
      if ((_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_framebuffer_object)
1934
          || _mesa_is_gles3(ctx)) {
1935
         *params = rb->NumSamples;
1936
         break;
1937
      }
1938
      /* fallthrough */
1939
   default:
1940
      _mesa_error(ctx, GL_INVALID_ENUM,
1941
                  "glGetRenderbufferParameterivEXT(target)");
1942
      return;
1943
   }
1944
}
1945
 
1946
 
1947
GLboolean GLAPIENTRY
1948
_mesa_IsFramebuffer(GLuint framebuffer)
1949
{
1950
   GET_CURRENT_CONTEXT(ctx);
1951
   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
1952
   if (framebuffer) {
1953
      struct gl_framebuffer *rb = _mesa_lookup_framebuffer(ctx, framebuffer);
1954
      if (rb != NULL && rb != &DummyFramebuffer)
1955
         return GL_TRUE;
1956
   }
1957
   return GL_FALSE;
1958
}
1959
 
1960
 
1961
/**
1962
 * Check if any of the attachments of the given framebuffer are textures
1963
 * (render to texture).  Call ctx->Driver.RenderTexture() for such
1964
 * attachments.
1965
 */
1966
static void
1967
check_begin_texture_render(struct gl_context *ctx, struct gl_framebuffer *fb)
1968
{
1969
   GLuint i;
1970
   ASSERT(ctx->Driver.RenderTexture);
1971
 
1972
   if (_mesa_is_winsys_fbo(fb))
1973
      return; /* can't render to texture with winsys framebuffers */
1974
 
1975
   for (i = 0; i < BUFFER_COUNT; i++) {
1976
      struct gl_renderbuffer_attachment *att = fb->Attachment + i;
1977
      if (att->Texture && att->Renderbuffer->TexImage
1978
          && driver_RenderTexture_is_safe(att)) {
1979
         ctx->Driver.RenderTexture(ctx, fb, att);
1980
      }
1981
   }
1982
}
1983
 
1984
 
1985
/**
1986
 * Examine all the framebuffer's attachments to see if any are textures.
1987
 * If so, call ctx->Driver.FinishRenderTexture() for each texture to
1988
 * notify the device driver that the texture image may have changed.
1989
 */
1990
static void
1991
check_end_texture_render(struct gl_context *ctx, struct gl_framebuffer *fb)
1992
{
1993
   if (_mesa_is_winsys_fbo(fb))
1994
      return; /* can't render to texture with winsys framebuffers */
1995
 
1996
   if (ctx->Driver.FinishRenderTexture) {
1997
      GLuint i;
1998
      for (i = 0; i < BUFFER_COUNT; i++) {
1999
         struct gl_renderbuffer_attachment *att = fb->Attachment + i;
2000
         struct gl_renderbuffer *rb = att->Renderbuffer;
2001
         if (rb && rb->NeedsFinishRenderTexture) {
2002
            ctx->Driver.FinishRenderTexture(ctx, rb);
2003
         }
2004
      }
2005
   }
2006
}
2007
 
2008
 
2009
static void
2010
bind_framebuffer(GLenum target, GLuint framebuffer, bool allow_user_names)
2011
{
2012
   struct gl_framebuffer *newDrawFb, *newReadFb;
2013
   struct gl_framebuffer *oldDrawFb, *oldReadFb;
2014
   GLboolean bindReadBuf, bindDrawBuf;
2015
   GET_CURRENT_CONTEXT(ctx);
2016
 
2017
#ifdef DEBUG
2018
   if (ctx->Extensions.ARB_framebuffer_object) {
2019
      ASSERT(ctx->Extensions.EXT_framebuffer_blit);
2020
   }
2021
#endif
2022
 
2023
   switch (target) {
2024
   case GL_DRAW_FRAMEBUFFER_EXT:
2025
      if (!ctx->Extensions.EXT_framebuffer_blit) {
2026
         _mesa_error(ctx, GL_INVALID_ENUM, "glBindFramebufferEXT(target)");
2027
         return;
2028
      }
2029
      bindDrawBuf = GL_TRUE;
2030
      bindReadBuf = GL_FALSE;
2031
      break;
2032
   case GL_READ_FRAMEBUFFER_EXT:
2033
      if (!ctx->Extensions.EXT_framebuffer_blit) {
2034
         _mesa_error(ctx, GL_INVALID_ENUM, "glBindFramebufferEXT(target)");
2035
         return;
2036
      }
2037
      bindDrawBuf = GL_FALSE;
2038
      bindReadBuf = GL_TRUE;
2039
      break;
2040
   case GL_FRAMEBUFFER_EXT:
2041
      bindDrawBuf = GL_TRUE;
2042
      bindReadBuf = GL_TRUE;
2043
      break;
2044
   default:
2045
      _mesa_error(ctx, GL_INVALID_ENUM, "glBindFramebufferEXT(target)");
2046
      return;
2047
   }
2048
 
2049
   if (framebuffer) {
2050
      /* Binding a user-created framebuffer object */
2051
      newDrawFb = _mesa_lookup_framebuffer(ctx, framebuffer);
2052
      if (newDrawFb == &DummyFramebuffer) {
2053
         /* ID was reserved, but no real framebuffer object made yet */
2054
         newDrawFb = NULL;
2055
      }
2056
      else if (!newDrawFb && !allow_user_names) {
2057
         /* All FBO IDs must be Gen'd */
2058
         _mesa_error(ctx, GL_INVALID_OPERATION, "glBindFramebuffer(buffer)");
2059
         return;
2060
      }
2061
 
2062
      if (!newDrawFb) {
2063
	 /* create new framebuffer object */
2064
	 newDrawFb = ctx->Driver.NewFramebuffer(ctx, framebuffer);
2065
	 if (!newDrawFb) {
2066
	    _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindFramebufferEXT");
2067
	    return;
2068
	 }
2069
         _mesa_HashInsert(ctx->Shared->FrameBuffers, framebuffer, newDrawFb);
2070
      }
2071
      newReadFb = newDrawFb;
2072
   }
2073
   else {
2074
      /* Binding the window system framebuffer (which was originally set
2075
       * with MakeCurrent).
2076
       */
2077
      newDrawFb = ctx->WinSysDrawBuffer;
2078
      newReadFb = ctx->WinSysReadBuffer;
2079
   }
2080
 
2081
   ASSERT(newDrawFb);
2082
   ASSERT(newDrawFb != &DummyFramebuffer);
2083
 
2084
   /* save pointers to current/old framebuffers */
2085
   oldDrawFb = ctx->DrawBuffer;
2086
   oldReadFb = ctx->ReadBuffer;
2087
 
2088
   /* check if really changing bindings */
2089
   if (oldDrawFb == newDrawFb)
2090
      bindDrawBuf = GL_FALSE;
2091
   if (oldReadFb == newReadFb)
2092
      bindReadBuf = GL_FALSE;
2093
 
2094
   /*
2095
    * OK, now bind the new Draw/Read framebuffers, if they're changing.
2096
    *
2097
    * We also check if we're beginning and/or ending render-to-texture.
2098
    * When a framebuffer with texture attachments is unbound, call
2099
    * ctx->Driver.FinishRenderTexture().
2100
    * When a framebuffer with texture attachments is bound, call
2101
    * ctx->Driver.RenderTexture().
2102
    *
2103
    * Note that if the ReadBuffer has texture attachments we don't consider
2104
    * that a render-to-texture case.
2105
    */
2106
   if (bindReadBuf) {
2107
      FLUSH_VERTICES(ctx, _NEW_BUFFERS);
2108
 
2109
      /* check if old readbuffer was render-to-texture */
2110
      check_end_texture_render(ctx, oldReadFb);
2111
 
2112
      _mesa_reference_framebuffer(&ctx->ReadBuffer, newReadFb);
2113
   }
2114
 
2115
   if (bindDrawBuf) {
2116
      FLUSH_VERTICES(ctx, _NEW_BUFFERS);
2117
 
2118
      /* check if old framebuffer had any texture attachments */
2119
      if (oldDrawFb)
2120
         check_end_texture_render(ctx, oldDrawFb);
2121
 
2122
      /* check if newly bound framebuffer has any texture attachments */
2123
      check_begin_texture_render(ctx, newDrawFb);
2124
 
2125
      _mesa_reference_framebuffer(&ctx->DrawBuffer, newDrawFb);
2126
   }
2127
 
2128
   if ((bindDrawBuf || bindReadBuf) && ctx->Driver.BindFramebuffer) {
2129
      ctx->Driver.BindFramebuffer(ctx, target, newDrawFb, newReadFb);
2130
   }
2131
}
2132
 
2133
void GLAPIENTRY
2134
_mesa_BindFramebuffer(GLenum target, GLuint framebuffer)
2135
{
2136
   GET_CURRENT_CONTEXT(ctx);
2137
 
2138
   /* OpenGL ES glBindFramebuffer and glBindFramebufferOES use this same entry
2139
    * point, but they allow the use of user-generated names.
2140
    */
2141
   bind_framebuffer(target, framebuffer, _mesa_is_gles(ctx));
2142
}
2143
 
2144
void GLAPIENTRY
2145
_mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer)
2146
{
2147
   /* This function should not be in the dispatch table for core profile /
2148
    * OpenGL 3.1, so execution should never get here in those cases -- no
2149
    * need for an explicit test.
2150
    */
2151
   bind_framebuffer(target, framebuffer, true);
2152
}
2153
 
2154
void GLAPIENTRY
2155
_mesa_DeleteFramebuffers(GLsizei n, const GLuint *framebuffers)
2156
{
2157
   GLint i;
2158
   GET_CURRENT_CONTEXT(ctx);
2159
 
2160
   FLUSH_VERTICES(ctx, _NEW_BUFFERS);
2161
 
2162
   for (i = 0; i < n; i++) {
2163
      if (framebuffers[i] > 0) {
2164
	 struct gl_framebuffer *fb;
2165
	 fb = _mesa_lookup_framebuffer(ctx, framebuffers[i]);
2166
	 if (fb) {
2167
            ASSERT(fb == &DummyFramebuffer || fb->Name == framebuffers[i]);
2168
 
2169
            /* check if deleting currently bound framebuffer object */
2170
            if (ctx->Extensions.EXT_framebuffer_blit) {
2171
               /* separate draw/read binding points */
2172
               if (fb == ctx->DrawBuffer) {
2173
                  /* bind default */
2174
                  ASSERT(fb->RefCount >= 2);
2175
                  _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, 0);
2176
               }
2177
               if (fb == ctx->ReadBuffer) {
2178
                  /* bind default */
2179
                  ASSERT(fb->RefCount >= 2);
2180
                  _mesa_BindFramebuffer(GL_READ_FRAMEBUFFER_EXT, 0);
2181
               }
2182
            }
2183
            else {
2184
               /* only one binding point for read/draw buffers */
2185
               if (fb == ctx->DrawBuffer || fb == ctx->ReadBuffer) {
2186
                  /* bind default */
2187
                  ASSERT(fb->RefCount >= 2);
2188
                  _mesa_BindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
2189
               }
2190
            }
2191
 
2192
	    /* remove from hash table immediately, to free the ID */
2193
	    _mesa_HashRemove(ctx->Shared->FrameBuffers, framebuffers[i]);
2194
 
2195
            if (fb != &DummyFramebuffer) {
2196
               /* But the object will not be freed until it's no longer
2197
                * bound in any context.
2198
                */
2199
               _mesa_reference_framebuffer(&fb, NULL);
2200
	    }
2201
	 }
2202
      }
2203
   }
2204
}
2205
 
2206
 
2207
void GLAPIENTRY
2208
_mesa_GenFramebuffers(GLsizei n, GLuint *framebuffers)
2209
{
2210
   GET_CURRENT_CONTEXT(ctx);
2211
   GLuint first;
2212
   GLint i;
2213
 
2214
   if (n < 0) {
2215
      _mesa_error(ctx, GL_INVALID_VALUE, "glGenFramebuffersEXT(n)");
2216
      return;
2217
   }
2218
 
2219
   if (!framebuffers)
2220
      return;
2221
 
2222
   first = _mesa_HashFindFreeKeyBlock(ctx->Shared->FrameBuffers, n);
2223
 
2224
   for (i = 0; i < n; i++) {
2225
      GLuint name = first + i;
2226
      framebuffers[i] = name;
2227
      /* insert dummy placeholder into hash table */
2228
      _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
2229
      _mesa_HashInsert(ctx->Shared->FrameBuffers, name, &DummyFramebuffer);
2230
      _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
2231
   }
2232
}
2233
 
2234
 
2235
 
2236
GLenum GLAPIENTRY
2237
_mesa_CheckFramebufferStatus(GLenum target)
2238
{
2239
   struct gl_framebuffer *buffer;
2240
   GET_CURRENT_CONTEXT(ctx);
2241
 
2242
   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0);
2243
 
2244
   if (MESA_VERBOSE & VERBOSE_API)
2245
      _mesa_debug(ctx, "glCheckFramebufferStatus(%s)\n",
2246
                  _mesa_lookup_enum_by_nr(target));
2247
 
2248
   buffer = get_framebuffer_target(ctx, target);
2249
   if (!buffer) {
2250
      _mesa_error(ctx, GL_INVALID_ENUM, "glCheckFramebufferStatus(target)");
2251
      return 0;
2252
   }
2253
 
2254
   if (_mesa_is_winsys_fbo(buffer)) {
2255
      /* The window system / default framebuffer is always complete */
2256
      return GL_FRAMEBUFFER_COMPLETE_EXT;
2257
   }
2258
 
2259
   /* No need to flush here */
2260
 
2261
   if (buffer->_Status != GL_FRAMEBUFFER_COMPLETE) {
2262
      _mesa_test_framebuffer_completeness(ctx, buffer);
2263
   }
2264
 
2265
   return buffer->_Status;
2266
}
2267
 
2268
 
2269
/**
2270
 * Replicate the src attachment point. Used by framebuffer_texture() when
2271
 * the same texture is attached at GL_DEPTH_ATTACHMENT and
2272
 * GL_STENCIL_ATTACHMENT.
2273
 */
2274
static void
2275
reuse_framebuffer_texture_attachment(struct gl_framebuffer *fb,
2276
                                     gl_buffer_index dst,
2277
                                     gl_buffer_index src)
2278
{
2279
   struct gl_renderbuffer_attachment *dst_att = &fb->Attachment[dst];
2280
   struct gl_renderbuffer_attachment *src_att = &fb->Attachment[src];
2281
 
2282
   assert(src_att->Texture != NULL);
2283
   assert(src_att->Renderbuffer != NULL);
2284
 
2285
   _mesa_reference_texobj(&dst_att->Texture, src_att->Texture);
2286
   _mesa_reference_renderbuffer(&dst_att->Renderbuffer, src_att->Renderbuffer);
2287
   dst_att->Type = src_att->Type;
2288
   dst_att->Complete = src_att->Complete;
2289
   dst_att->TextureLevel = src_att->TextureLevel;
2290
   dst_att->Zoffset = src_att->Zoffset;
2291
}
2292
 
2293
 
2294
/**
2295
 * Common code called by glFramebufferTexture1D/2D/3DEXT() and
2296
 * glFramebufferTextureLayerEXT().
2297
 * Note: glFramebufferTextureLayerEXT() has no textarget parameter so we'll
2298
 * get textarget=0 in that case.
2299
 */
2300
static void
2301
framebuffer_texture(struct gl_context *ctx, const char *caller, GLenum target,
2302
                    GLenum attachment, GLenum textarget, GLuint texture,
2303
                    GLint level, GLint zoffset, GLboolean layered)
2304
{
2305
   struct gl_renderbuffer_attachment *att;
2306
   struct gl_texture_object *texObj = NULL;
2307
   struct gl_framebuffer *fb;
2308
   GLenum maxLevelsTarget;
2309
 
2310
   fb = get_framebuffer_target(ctx, target);
2311
   if (!fb) {
2312
      _mesa_error(ctx, GL_INVALID_ENUM,
2313
                  "glFramebufferTexture%sEXT(target=0x%x)", caller, target);
2314
      return;
2315
   }
2316
 
2317
   /* check framebuffer binding */
2318
   if (_mesa_is_winsys_fbo(fb)) {
2319
      _mesa_error(ctx, GL_INVALID_OPERATION,
2320
                  "glFramebufferTexture%sEXT", caller);
2321
      return;
2322
   }
2323
 
2324
   /* The textarget, level, and zoffset parameters are only validated if
2325
    * texture is non-zero.
2326
    */
2327
   if (texture) {
2328
      GLboolean err = GL_TRUE;
2329
 
2330
      texObj = _mesa_lookup_texture(ctx, texture);
2331
      if (texObj != NULL) {
2332
         if (textarget == 0) {
2333
            /* If textarget == 0 it means we're being called by
2334
             * glFramebufferTextureLayer() and textarget is not used.
2335
             * The only legal texture types for that function are 3D and
2336
             * 1D/2D arrays textures.
2337
             */
2338
            err = (texObj->Target != GL_TEXTURE_3D) &&
2339
                (texObj->Target != GL_TEXTURE_1D_ARRAY_EXT) &&
2340
                (texObj->Target != GL_TEXTURE_2D_ARRAY_EXT) &&
2341
                (texObj->Target != GL_TEXTURE_CUBE_MAP_ARRAY) &&
2342
                (texObj->Target != GL_TEXTURE_2D_MULTISAMPLE_ARRAY);
2343
         }
2344
         else {
2345
            /* Make sure textarget is consistent with the texture's type */
2346
            err = (texObj->Target == GL_TEXTURE_CUBE_MAP)
2347
                ? !_mesa_is_cube_face(textarget)
2348
                : (texObj->Target != textarget);
2349
         }
2350
      }
2351
      else {
2352
         /* can't render to a non-existant texture */
2353
         _mesa_error(ctx, GL_INVALID_OPERATION,
2354
                     "glFramebufferTexture%sEXT(non existant texture)",
2355
                     caller);
2356
         return;
2357
      }
2358
 
2359
      if (err) {
2360
         _mesa_error(ctx, GL_INVALID_OPERATION,
2361
                     "glFramebufferTexture%sEXT(texture target mismatch)",
2362
                     caller);
2363
         return;
2364
      }
2365
 
2366
      if (texObj->Target == GL_TEXTURE_3D) {
2367
         const GLint maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1);
2368
         if (zoffset < 0 || zoffset >= maxSize) {
2369
            _mesa_error(ctx, GL_INVALID_VALUE,
2370
                        "glFramebufferTexture%sEXT(zoffset)", caller);
2371
            return;
2372
         }
2373
      }
2374
      else if ((texObj->Target == GL_TEXTURE_1D_ARRAY_EXT) ||
2375
               (texObj->Target == GL_TEXTURE_2D_ARRAY_EXT) ||
2376
               (texObj->Target == GL_TEXTURE_CUBE_MAP_ARRAY) ||
2377
               (texObj->Target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY)) {
2378
         if (zoffset < 0 ||
2379
             zoffset >= (GLint) ctx->Const.MaxArrayTextureLayers) {
2380
            _mesa_error(ctx, GL_INVALID_VALUE,
2381
                        "glFramebufferTexture%sEXT(layer)", caller);
2382
            return;
2383
         }
2384
      }
2385
 
2386
      maxLevelsTarget = textarget ? textarget : texObj->Target;
2387
      if ((level < 0) ||
2388
          (level >= _mesa_max_texture_levels(ctx, maxLevelsTarget))) {
2389
         _mesa_error(ctx, GL_INVALID_VALUE,
2390
                     "glFramebufferTexture%sEXT(level)", caller);
2391
         return;
2392
      }
2393
   }
2394
 
2395
   att = _mesa_get_attachment(ctx, fb, attachment);
2396
   if (att == NULL) {
2397
      _mesa_error(ctx, GL_INVALID_ENUM,
2398
                  "glFramebufferTexture%sEXT(attachment)", caller);
2399
      return;
2400
   }
2401
 
2402
   FLUSH_VERTICES(ctx, _NEW_BUFFERS);
2403
 
2404
   _glthread_LOCK_MUTEX(fb->Mutex);
2405
   if (texObj) {
2406
      if (attachment == GL_DEPTH_ATTACHMENT &&
2407
          texObj == fb->Attachment[BUFFER_STENCIL].Texture &&
2408
          level == fb->Attachment[BUFFER_STENCIL].TextureLevel &&
2409
          _mesa_tex_target_to_face(textarget) ==
2410
          fb->Attachment[BUFFER_STENCIL].CubeMapFace &&
2411
          zoffset == fb->Attachment[BUFFER_STENCIL].Zoffset) {
2412
	 /* The texture object is already attached to the stencil attachment
2413
	  * point. Don't create a new renderbuffer; just reuse the stencil
2414
	  * attachment's. This is required to prevent a GL error in
2415
	  * glGetFramebufferAttachmentParameteriv(GL_DEPTH_STENCIL).
2416
	  */
2417
	 reuse_framebuffer_texture_attachment(fb, BUFFER_DEPTH,
2418
	                                      BUFFER_STENCIL);
2419
      } else if (attachment == GL_STENCIL_ATTACHMENT &&
2420
	         texObj == fb->Attachment[BUFFER_DEPTH].Texture &&
2421
                 level == fb->Attachment[BUFFER_DEPTH].TextureLevel &&
2422
                 _mesa_tex_target_to_face(textarget) ==
2423
                 fb->Attachment[BUFFER_DEPTH].CubeMapFace &&
2424
                 zoffset == fb->Attachment[BUFFER_DEPTH].Zoffset) {
2425
	 /* As above, but with depth and stencil transposed. */
2426
	 reuse_framebuffer_texture_attachment(fb, BUFFER_STENCIL,
2427
	                                      BUFFER_DEPTH);
2428
      } else {
2429
	 _mesa_set_texture_attachment(ctx, fb, att, texObj, textarget,
2430
	                              level, zoffset, layered);
2431
	 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
2432
	    /* Above we created a new renderbuffer and attached it to the
2433
	     * depth attachment point. Now attach it to the stencil attachment
2434
	     * point too.
2435
	     */
2436
	    assert(att == &fb->Attachment[BUFFER_DEPTH]);
2437
	    reuse_framebuffer_texture_attachment(fb,BUFFER_STENCIL,
2438
	                                         BUFFER_DEPTH);
2439
	 }
2440
      }
2441
 
2442
      /* Set the render-to-texture flag.  We'll check this flag in
2443
       * glTexImage() and friends to determine if we need to revalidate
2444
       * any FBOs that might be rendering into this texture.
2445
       * This flag never gets cleared since it's non-trivial to determine
2446
       * when all FBOs might be done rendering to this texture.  That's OK
2447
       * though since it's uncommon to render to a texture then repeatedly
2448
       * call glTexImage() to change images in the texture.
2449
       */
2450
      texObj->_RenderToTexture = GL_TRUE;
2451
   }
2452
   else {
2453
      _mesa_remove_attachment(ctx, att);
2454
      if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
2455
	 assert(att == &fb->Attachment[BUFFER_DEPTH]);
2456
	 _mesa_remove_attachment(ctx, &fb->Attachment[BUFFER_STENCIL]);
2457
      }
2458
   }
2459
 
2460
   invalidate_framebuffer(fb);
2461
 
2462
   _glthread_UNLOCK_MUTEX(fb->Mutex);
2463
}
2464
 
2465
 
2466
 
2467
void GLAPIENTRY
2468
_mesa_FramebufferTexture1D(GLenum target, GLenum attachment,
2469
                              GLenum textarget, GLuint texture, GLint level)
2470
{
2471
   GET_CURRENT_CONTEXT(ctx);
2472
 
2473
   if (texture != 0) {
2474
      GLboolean error;
2475
 
2476
      switch (textarget) {
2477
      case GL_TEXTURE_1D:
2478
         error = GL_FALSE;
2479
         break;
2480
      case GL_TEXTURE_1D_ARRAY:
2481
         error = !ctx->Extensions.EXT_texture_array;
2482
         break;
2483
      default:
2484
         error = GL_TRUE;
2485
      }
2486
 
2487
      if (error) {
2488
         _mesa_error(ctx, GL_INVALID_OPERATION,
2489
                     "glFramebufferTexture1DEXT(textarget=%s)",
2490
                     _mesa_lookup_enum_by_nr(textarget));
2491
         return;
2492
      }
2493
   }
2494
 
2495
   framebuffer_texture(ctx, "1D", target, attachment, textarget, texture,
2496
                       level, 0, GL_FALSE);
2497
}
2498
 
2499
 
2500
void GLAPIENTRY
2501
_mesa_FramebufferTexture2D(GLenum target, GLenum attachment,
2502
                              GLenum textarget, GLuint texture, GLint level)
2503
{
2504
   GET_CURRENT_CONTEXT(ctx);
2505
 
2506
   if (texture != 0) {
2507
      GLboolean error;
2508
 
2509
      switch (textarget) {
2510
      case GL_TEXTURE_2D:
2511
         error = GL_FALSE;
2512
         break;
2513
      case GL_TEXTURE_RECTANGLE:
2514
         error = _mesa_is_gles(ctx)
2515
            || !ctx->Extensions.NV_texture_rectangle;
2516
         break;
2517
      case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2518
      case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2519
      case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2520
      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2521
      case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2522
      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2523
         error = !ctx->Extensions.ARB_texture_cube_map;
2524
         break;
2525
      case GL_TEXTURE_2D_ARRAY:
2526
         error = (_mesa_is_gles(ctx) && ctx->Version < 30)
2527
            || !ctx->Extensions.EXT_texture_array;
2528
         break;
2529
      case GL_TEXTURE_2D_MULTISAMPLE:
2530
      case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
2531
         error = _mesa_is_gles(ctx)
2532
            || !ctx->Extensions.ARB_texture_multisample;
2533
         break;
2534
      default:
2535
         error = GL_TRUE;
2536
      }
2537
 
2538
      if (error) {
2539
         _mesa_error(ctx, GL_INVALID_OPERATION,
2540
                     "glFramebufferTexture2DEXT(textarget=%s)",
2541
                     _mesa_lookup_enum_by_nr(textarget));
2542
         return;
2543
      }
2544
   }
2545
 
2546
   framebuffer_texture(ctx, "2D", target, attachment, textarget, texture,
2547
                       level, 0, GL_FALSE);
2548
}
2549
 
2550
 
2551
void GLAPIENTRY
2552
_mesa_FramebufferTexture3D(GLenum target, GLenum attachment,
2553
                              GLenum textarget, GLuint texture,
2554
                              GLint level, GLint zoffset)
2555
{
2556
   GET_CURRENT_CONTEXT(ctx);
2557
 
2558
   if ((texture != 0) && (textarget != GL_TEXTURE_3D)) {
2559
      _mesa_error(ctx, GL_INVALID_OPERATION,
2560
                  "glFramebufferTexture3DEXT(textarget)");
2561
      return;
2562
   }
2563
 
2564
   framebuffer_texture(ctx, "3D", target, attachment, textarget, texture,
2565
                       level, zoffset, GL_FALSE);
2566
}
2567
 
2568
 
2569
void GLAPIENTRY
2570
_mesa_FramebufferTextureLayer(GLenum target, GLenum attachment,
2571
                                 GLuint texture, GLint level, GLint layer)
2572
{
2573
   GET_CURRENT_CONTEXT(ctx);
2574
 
2575
   framebuffer_texture(ctx, "Layer", target, attachment, 0, texture,
2576
                       level, layer, GL_FALSE);
2577
}
2578
 
2579
 
2580
void GLAPIENTRY
2581
_mesa_FramebufferTexture(GLenum target, GLenum attachment,
2582
                         GLuint texture, GLint level)
2583
{
2584
   GET_CURRENT_CONTEXT(ctx);
2585
 
2586
   if (ctx->Version >= 32 || ctx->Extensions.ARB_geometry_shader4) {
2587
      framebuffer_texture(ctx, "Layer", target, attachment, 0, texture,
2588
                          level, 0, GL_TRUE);
2589
   } else {
2590
      _mesa_error(ctx, GL_INVALID_OPERATION,
2591
                  "unsupported function (glFramebufferTexture) called");
2592
   }
2593
}
2594
 
2595
 
2596
void GLAPIENTRY
2597
_mesa_FramebufferRenderbuffer(GLenum target, GLenum attachment,
2598
                                 GLenum renderbufferTarget,
2599
                                 GLuint renderbuffer)
2600
{
2601
   struct gl_renderbuffer_attachment *att;
2602
   struct gl_framebuffer *fb;
2603
   struct gl_renderbuffer *rb;
2604
   GET_CURRENT_CONTEXT(ctx);
2605
 
2606
   fb = get_framebuffer_target(ctx, target);
2607
   if (!fb) {
2608
      _mesa_error(ctx, GL_INVALID_ENUM, "glFramebufferRenderbufferEXT(target)");
2609
      return;
2610
   }
2611
 
2612
   if (renderbufferTarget != GL_RENDERBUFFER_EXT) {
2613
      _mesa_error(ctx, GL_INVALID_ENUM,
2614
                  "glFramebufferRenderbufferEXT(renderbufferTarget)");
2615
      return;
2616
   }
2617
 
2618
   if (_mesa_is_winsys_fbo(fb)) {
2619
      /* Can't attach new renderbuffers to a window system framebuffer */
2620
      _mesa_error(ctx, GL_INVALID_OPERATION, "glFramebufferRenderbufferEXT");
2621
      return;
2622
   }
2623
 
2624
   att = _mesa_get_attachment(ctx, fb, attachment);
2625
   if (att == NULL) {
2626
      _mesa_error(ctx, GL_INVALID_ENUM,
2627
                  "glFramebufferRenderbufferEXT(invalid attachment %s)",
2628
                  _mesa_lookup_enum_by_nr(attachment));
2629
      return;
2630
   }
2631
 
2632
   if (renderbuffer) {
2633
      rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
2634
      if (!rb) {
2635
	 _mesa_error(ctx, GL_INVALID_OPERATION,
2636
		     "glFramebufferRenderbufferEXT(non-existant"
2637
                     " renderbuffer %u)", renderbuffer);
2638
	 return;
2639
      }
2640
      else if (rb == &DummyRenderbuffer) {
2641
         /* This is what NVIDIA does */
2642
	 _mesa_error(ctx, GL_INVALID_VALUE,
2643
		     "glFramebufferRenderbufferEXT(renderbuffer %u)",
2644
                     renderbuffer);
2645
	 return;
2646
      }
2647
   }
2648
   else {
2649
      /* remove renderbuffer attachment */
2650
      rb = NULL;
2651
   }
2652
 
2653
   if (attachment == GL_DEPTH_STENCIL_ATTACHMENT &&
2654
       rb && rb->Format != MESA_FORMAT_NONE) {
2655
      /* make sure the renderbuffer is a depth/stencil format */
2656
      const GLenum baseFormat = _mesa_get_format_base_format(rb->Format);
2657
      if (baseFormat != GL_DEPTH_STENCIL) {
2658
         _mesa_error(ctx, GL_INVALID_OPERATION,
2659
                     "glFramebufferRenderbufferEXT(renderbuffer"
2660
                     " is not DEPTH_STENCIL format)");
2661
         return;
2662
      }
2663
   }
2664
 
2665
 
2666
   FLUSH_VERTICES(ctx, _NEW_BUFFERS);
2667
 
2668
   assert(ctx->Driver.FramebufferRenderbuffer);
2669
   ctx->Driver.FramebufferRenderbuffer(ctx, fb, attachment, rb);
2670
 
2671
   /* Some subsequent GL commands may depend on the framebuffer's visual
2672
    * after the binding is updated.  Update visual info now.
2673
    */
2674
   _mesa_update_framebuffer_visual(ctx, fb);
2675
}
2676
 
2677
 
2678
void GLAPIENTRY
2679
_mesa_GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment,
2680
                                             GLenum pname, GLint *params)
2681
{
2682
   const struct gl_renderbuffer_attachment *att;
2683
   struct gl_framebuffer *buffer;
2684
   GLenum err;
2685
   GET_CURRENT_CONTEXT(ctx);
2686
 
2687
   /* The error differs in GL and GLES. */
2688
   err = _mesa_is_desktop_gl(ctx) ? GL_INVALID_OPERATION : GL_INVALID_ENUM;
2689
 
2690
   buffer = get_framebuffer_target(ctx, target);
2691
   if (!buffer) {
2692
      _mesa_error(ctx, GL_INVALID_ENUM,
2693
                  "glGetFramebufferAttachmentParameterivEXT(target)");
2694
      return;
2695
   }
2696
 
2697
   if (_mesa_is_winsys_fbo(buffer)) {
2698
      /* Page 126 (page 136 of the PDF) of the OpenGL ES 2.0.25 spec
2699
       * says:
2700
       *
2701
       *     "If the framebuffer currently bound to target is zero, then
2702
       *     INVALID_OPERATION is generated."
2703
       *
2704
       * The EXT_framebuffer_object spec has the same wording, and the
2705
       * OES_framebuffer_object spec refers to the EXT_framebuffer_object
2706
       * spec.
2707
       */
2708
      if ((!_mesa_is_desktop_gl(ctx) || !ctx->Extensions.ARB_framebuffer_object)
2709
          && !_mesa_is_gles3(ctx)) {
2710
	 _mesa_error(ctx, GL_INVALID_OPERATION,
2711
		     "glGetFramebufferAttachmentParameteriv(bound FBO = 0)");
2712
	 return;
2713
      }
2714
 
2715
      if (_mesa_is_gles3(ctx) && attachment != GL_BACK &&
2716
          attachment != GL_DEPTH && attachment != GL_STENCIL) {
2717
         _mesa_error(ctx, GL_INVALID_OPERATION,
2718
                     "glGetFramebufferAttachmentParameteriv(attachment)");
2719
         return;
2720
      }
2721
      /* the default / window-system FBO */
2722
      att = _mesa_get_fb0_attachment(ctx, buffer, attachment);
2723
   }
2724
   else {
2725
      /* user-created framebuffer FBO */
2726
      att = _mesa_get_attachment(ctx, buffer, attachment);
2727
   }
2728
 
2729
   if (att == NULL) {
2730
      _mesa_error(ctx, GL_INVALID_ENUM,
2731
                  "glGetFramebufferAttachmentParameterivEXT(attachment)");
2732
      return;
2733
   }
2734
 
2735
   if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
2736
      /* the depth and stencil attachments must point to the same buffer */
2737
      const struct gl_renderbuffer_attachment *depthAtt, *stencilAtt;
2738
      depthAtt = _mesa_get_attachment(ctx, buffer, GL_DEPTH_ATTACHMENT);
2739
      stencilAtt = _mesa_get_attachment(ctx, buffer, GL_STENCIL_ATTACHMENT);
2740
      if (depthAtt->Renderbuffer != stencilAtt->Renderbuffer) {
2741
         _mesa_error(ctx, GL_INVALID_OPERATION,
2742
                     "glGetFramebufferAttachmentParameterivEXT(DEPTH/STENCIL"
2743
                     " attachments differ)");
2744
         return;
2745
      }
2746
   }
2747
 
2748
   /* No need to flush here */
2749
 
2750
   switch (pname) {
2751
   case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT:
2752
      *params = _mesa_is_winsys_fbo(buffer)
2753
         ? GL_FRAMEBUFFER_DEFAULT : att->Type;
2754
      return;
2755
   case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT:
2756
      if (att->Type == GL_RENDERBUFFER_EXT) {
2757
	 *params = att->Renderbuffer->Name;
2758
      }
2759
      else if (att->Type == GL_TEXTURE) {
2760
	 *params = att->Texture->Name;
2761
      }
2762
      else {
2763
         assert(att->Type == GL_NONE);
2764
         if (_mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx)) {
2765
            *params = 0;
2766
         } else {
2767
            goto invalid_pname_enum;
2768
         }
2769
      }
2770
      return;
2771
   case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT:
2772
      if (att->Type == GL_TEXTURE) {
2773
	 *params = att->TextureLevel;
2774
      }
2775
      else if (att->Type == GL_NONE) {
2776
         _mesa_error(ctx, err,
2777
                     "glGetFramebufferAttachmentParameterivEXT(pname)");
2778
      }
2779
      else {
2780
         goto invalid_pname_enum;
2781
      }
2782
      return;
2783
   case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT:
2784
      if (att->Type == GL_TEXTURE) {
2785
         if (att->Texture && att->Texture->Target == GL_TEXTURE_CUBE_MAP) {
2786
            *params = GL_TEXTURE_CUBE_MAP_POSITIVE_X + att->CubeMapFace;
2787
         }
2788
         else {
2789
            *params = 0;
2790
         }
2791
      }
2792
      else if (att->Type == GL_NONE) {
2793
         _mesa_error(ctx, err,
2794
                     "glGetFramebufferAttachmentParameterivEXT(pname)");
2795
      }
2796
      else {
2797
         goto invalid_pname_enum;
2798
      }
2799
      return;
2800
   case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT:
2801
      if (ctx->API == API_OPENGLES) {
2802
         goto invalid_pname_enum;
2803
      } else if (att->Type == GL_NONE) {
2804
         _mesa_error(ctx, err,
2805
                     "glGetFramebufferAttachmentParameterivEXT(pname)");
2806
      } else if (att->Type == GL_TEXTURE) {
2807
         if (att->Texture && att->Texture->Target == GL_TEXTURE_3D) {
2808
            *params = att->Zoffset;
2809
         }
2810
         else {
2811
            *params = 0;
2812
         }
2813
      }
2814
      else {
2815
         goto invalid_pname_enum;
2816
      }
2817
      return;
2818
   case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
2819
      if ((!_mesa_is_desktop_gl(ctx) || !ctx->Extensions.ARB_framebuffer_object)
2820
          && !_mesa_is_gles3(ctx)) {
2821
         goto invalid_pname_enum;
2822
      }
2823
      else if (att->Type == GL_NONE) {
2824
         _mesa_error(ctx, err,
2825
                     "glGetFramebufferAttachmentParameterivEXT(pname)");
2826
      }
2827
      else {
2828
         if (ctx->Extensions.EXT_framebuffer_sRGB) {
2829
            *params = _mesa_get_format_color_encoding(att->Renderbuffer->Format);
2830
         }
2831
         else {
2832
            /* According to ARB_framebuffer_sRGB, we should return LINEAR
2833
             * if the sRGB conversion is unsupported. */
2834
            *params = GL_LINEAR;
2835
         }
2836
      }
2837
      return;
2838
   case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
2839
      if ((ctx->API != API_OPENGL_COMPAT || !ctx->Extensions.ARB_framebuffer_object)
2840
          && ctx->API != API_OPENGL_CORE
2841
          && !_mesa_is_gles3(ctx)) {
2842
         goto invalid_pname_enum;
2843
      }
2844
      else if (att->Type == GL_NONE) {
2845
         _mesa_error(ctx, err,
2846
                     "glGetFramebufferAttachmentParameterivEXT(pname)");
2847
      }
2848
      else {
2849
         gl_format format = att->Renderbuffer->Format;
2850
 
2851
         /* Page 235 (page 247 of the PDF) in section 6.1.13 of the OpenGL ES
2852
          * 3.0.1 spec says:
2853
          *
2854
          *     "If pname is FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE.... If
2855
          *     attachment is DEPTH_STENCIL_ATTACHMENT the query will fail and
2856
          *     generate an INVALID_OPERATION error.
2857
          */
2858
         if (_mesa_is_gles3(ctx) && attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
2859
            _mesa_error(ctx, GL_INVALID_OPERATION,
2860
                        "glGetFramebufferAttachmentParameteriv(cannot query "
2861
                        "GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE of "
2862
                        "GL_DEPTH_STENCIL_ATTACHMENT");
2863
            return;
2864
         }
2865
 
2866
         if (format == MESA_FORMAT_S8) {
2867
            /* special cases */
2868
            *params = GL_INDEX;
2869
         }
2870
         else if (format == MESA_FORMAT_Z32_FLOAT_X24S8) {
2871
            /* depends on the attachment parameter */
2872
            if (attachment == GL_STENCIL_ATTACHMENT) {
2873
               *params = GL_INDEX;
2874
            }
2875
            else {
2876
               *params = GL_FLOAT;
2877
            }
2878
         }
2879
         else {
2880
            *params = _mesa_get_format_datatype(format);
2881
         }
2882
      }
2883
      return;
2884
   case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
2885
   case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
2886
   case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
2887
   case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
2888
   case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
2889
   case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
2890
      if ((!_mesa_is_desktop_gl(ctx) || !ctx->Extensions.ARB_framebuffer_object)
2891
          && !_mesa_is_gles3(ctx)) {
2892
         goto invalid_pname_enum;
2893
      }
2894
      else if (att->Type == GL_NONE) {
2895
         _mesa_error(ctx, err,
2896
                     "glGetFramebufferAttachmentParameterivEXT(pname)");
2897
      }
2898
      else if (att->Texture) {
2899
         const struct gl_texture_image *texImage =
2900
            _mesa_select_tex_image(ctx, att->Texture, att->Texture->Target,
2901
                                   att->TextureLevel);
2902
         if (texImage) {
2903
            *params = get_component_bits(pname, texImage->_BaseFormat,
2904
                                         texImage->TexFormat);
2905
         }
2906
         else {
2907
            *params = 0;
2908
         }
2909
      }
2910
      else if (att->Renderbuffer) {
2911
         *params = get_component_bits(pname, att->Renderbuffer->_BaseFormat,
2912
                                      att->Renderbuffer->Format);
2913
      }
2914
      else {
2915
         _mesa_problem(ctx, "glGetFramebufferAttachmentParameterivEXT:"
2916
                       " invalid FBO attachment structure");
2917
      }
2918
      return;
2919
   default:
2920
      goto invalid_pname_enum;
2921
   }
2922
 
2923
   return;
2924
 
2925
invalid_pname_enum:
2926
   _mesa_error(ctx, GL_INVALID_ENUM,
2927
               "glGetFramebufferAttachmentParameteriv(pname)");
2928
   return;
2929
}
2930
 
2931
 
2932
void GLAPIENTRY
2933
_mesa_GenerateMipmap(GLenum target)
2934
{
2935
   struct gl_texture_image *srcImage;
2936
   struct gl_texture_object *texObj;
2937
   GLboolean error;
2938
 
2939
   GET_CURRENT_CONTEXT(ctx);
2940
 
2941
   FLUSH_VERTICES(ctx, 0);
2942
 
2943
   switch (target) {
2944
   case GL_TEXTURE_1D:
2945
      error = _mesa_is_gles(ctx);
2946
      break;
2947
   case GL_TEXTURE_2D:
2948
      error = GL_FALSE;
2949
      break;
2950
   case GL_TEXTURE_3D:
2951
      error = ctx->API == API_OPENGLES;
2952
      break;
2953
   case GL_TEXTURE_CUBE_MAP:
2954
      error = !ctx->Extensions.ARB_texture_cube_map;
2955
      break;
2956
   case GL_TEXTURE_1D_ARRAY:
2957
      error = _mesa_is_gles(ctx) || !ctx->Extensions.EXT_texture_array;
2958
      break;
2959
   case GL_TEXTURE_2D_ARRAY:
2960
      error = (_mesa_is_gles(ctx) && ctx->Version < 30)
2961
         || !ctx->Extensions.EXT_texture_array;
2962
      break;
2963
   default:
2964
      error = GL_TRUE;
2965
   }
2966
 
2967
   if (error) {
2968
      _mesa_error(ctx, GL_INVALID_ENUM, "glGenerateMipmapEXT(target=%s)",
2969
                  _mesa_lookup_enum_by_nr(target));
2970
      return;
2971
   }
2972
 
2973
   texObj = _mesa_get_current_tex_object(ctx, target);
2974
 
2975
   if (texObj->BaseLevel >= texObj->MaxLevel) {
2976
      /* nothing to do */
2977
      return;
2978
   }
2979
 
2980
   if (texObj->Target == GL_TEXTURE_CUBE_MAP &&
2981
       !_mesa_cube_complete(texObj)) {
2982
      _mesa_error(ctx, GL_INVALID_OPERATION,
2983
                  "glGenerateMipmap(incomplete cube map)");
2984
      return;
2985
   }
2986
 
2987
   _mesa_lock_texture(ctx, texObj);
2988
 
2989
   srcImage = _mesa_select_tex_image(ctx, texObj, target, texObj->BaseLevel);
2990
   if (!srcImage) {
2991
      _mesa_unlock_texture(ctx, texObj);
2992
      _mesa_error(ctx, GL_INVALID_OPERATION,
2993
                  "glGenerateMipmap(zero size base image)");
2994
      return;
2995
   }
2996
 
2997
   if (_mesa_is_enum_format_integer(srcImage->InternalFormat) ||
2998
       _mesa_is_depthstencil_format(srcImage->InternalFormat) ||
2999
       _mesa_is_stencil_format(srcImage->InternalFormat)) {
3000
      _mesa_unlock_texture(ctx, texObj);
3001
      _mesa_error(ctx, GL_INVALID_OPERATION,
3002
                  "glGenerateMipmap(invalid internal format)");
3003
      return;
3004
   }
3005
 
3006
   if (target == GL_TEXTURE_CUBE_MAP) {
3007
      GLuint face;
3008
      for (face = 0; face < 6; face++)
3009
	 ctx->Driver.GenerateMipmap(ctx,
3010
				    GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + face,
3011
				    texObj);
3012
   }
3013
   else {
3014
      ctx->Driver.GenerateMipmap(ctx, target, texObj);
3015
   }
3016
   _mesa_unlock_texture(ctx, texObj);
3017
}
3018
 
3019
 
3020
static const struct gl_renderbuffer_attachment *
3021
find_attachment(const struct gl_framebuffer *fb,
3022
                const struct gl_renderbuffer *rb)
3023
{
3024
   GLuint i;
3025
   for (i = 0; i < Elements(fb->Attachment); i++) {
3026
      if (fb->Attachment[i].Renderbuffer == rb)
3027
         return &fb->Attachment[i];
3028
   }
3029
   return NULL;
3030
}
3031
 
3032
 
3033
/**
3034
 * Helper function for checking if the datatypes of color buffers are
3035
 * compatible for glBlitFramebuffer.  From the 3.1 spec, page 198:
3036
 *
3037
 * "GL_INVALID_OPERATION is generated if mask contains GL_COLOR_BUFFER_BIT
3038
 *  and any of the following conditions hold:
3039
 *   - The read buffer contains fixed-point or floating-point values and any
3040
 *     draw buffer contains neither fixed-point nor floating-point values.
3041
 *   - The read buffer contains unsigned integer values and any draw buffer
3042
 *     does not contain unsigned integer values.
3043
 *   - The read buffer contains signed integer values and any draw buffer
3044
 *     does not contain signed integer values."
3045
 */
3046
static GLboolean
3047
compatible_color_datatypes(gl_format srcFormat, gl_format dstFormat)
3048
{
3049
   GLenum srcType = _mesa_get_format_datatype(srcFormat);
3050
   GLenum dstType = _mesa_get_format_datatype(dstFormat);
3051
 
3052
   if (srcType != GL_INT && srcType != GL_UNSIGNED_INT) {
3053
      assert(srcType == GL_UNSIGNED_NORMALIZED ||
3054
             srcType == GL_SIGNED_NORMALIZED ||
3055
             srcType == GL_FLOAT);
3056
      /* Boil any of those types down to GL_FLOAT */
3057
      srcType = GL_FLOAT;
3058
   }
3059
 
3060
   if (dstType != GL_INT && dstType != GL_UNSIGNED_INT) {
3061
      assert(dstType == GL_UNSIGNED_NORMALIZED ||
3062
             dstType == GL_SIGNED_NORMALIZED ||
3063
             dstType == GL_FLOAT);
3064
      /* Boil any of those types down to GL_FLOAT */
3065
      dstType = GL_FLOAT;
3066
   }
3067
 
3068
   return srcType == dstType;
3069
}
3070
 
3071
 
3072
static GLboolean
3073
compatible_resolve_formats(const struct gl_renderbuffer *readRb,
3074
                           const struct gl_renderbuffer *drawRb)
3075
{
3076
   GLenum readFormat, drawFormat;
3077
 
3078
   /* The simple case where we know the backing Mesa formats are the same.
3079
    */
3080
   if (_mesa_get_srgb_format_linear(readRb->Format) ==
3081
       _mesa_get_srgb_format_linear(drawRb->Format)) {
3082
      return GL_TRUE;
3083
   }
3084
 
3085
   /* The Mesa formats are different, so we must check whether the internal
3086
    * formats are compatible.
3087
    *
3088
    * Under some circumstances, the user may request e.g. two GL_RGBA8
3089
    * textures and get two entirely different Mesa formats like RGBA8888 and
3090
    * ARGB8888. Drivers behaving like that should be able to cope with
3091
    * non-matching formats by themselves, because it's not the user's fault.
3092
    *
3093
    * Blits between linear and sRGB formats are also allowed.
3094
    */
3095
   readFormat = _mesa_get_nongeneric_internalformat(readRb->InternalFormat);
3096
   drawFormat = _mesa_get_nongeneric_internalformat(drawRb->InternalFormat);
3097
   readFormat = _mesa_get_linear_internalformat(readFormat);
3098
   drawFormat = _mesa_get_linear_internalformat(drawFormat);
3099
 
3100
   if (readFormat == drawFormat) {
3101
      return GL_TRUE;
3102
   }
3103
 
3104
   return GL_FALSE;
3105
}
3106
 
3107
static GLboolean
3108
is_valid_blit_filter(const struct gl_context *ctx, GLenum filter)
3109
{
3110
   switch (filter) {
3111
   case GL_NEAREST:
3112
   case GL_LINEAR:
3113
      return true;
3114
   case GL_SCALED_RESOLVE_FASTEST_EXT:
3115
   case GL_SCALED_RESOLVE_NICEST_EXT:
3116
      return ctx->Extensions.EXT_framebuffer_multisample_blit_scaled;
3117
   default:
3118
      return false;
3119
   }
3120
}
3121
 
3122
/**
3123
 * Blit rectangular region, optionally from one framebuffer to another.
3124
 *
3125
 * Note, if the src buffer is multisampled and the dest is not, this is
3126
 * when the samples must be resolved to a single color.
3127
 */
3128
void GLAPIENTRY
3129
_mesa_BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
3130
                         GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
3131
                         GLbitfield mask, GLenum filter)
3132
{
3133
   const GLbitfield legalMaskBits = (GL_COLOR_BUFFER_BIT |
3134
                                     GL_DEPTH_BUFFER_BIT |
3135
                                     GL_STENCIL_BUFFER_BIT);
3136
   const struct gl_framebuffer *readFb, *drawFb;
3137
   GET_CURRENT_CONTEXT(ctx);
3138
 
3139
   FLUSH_VERTICES(ctx, 0);
3140
 
3141
   if (MESA_VERBOSE & VERBOSE_API)
3142
      _mesa_debug(ctx,
3143
                  "glBlitFramebuffer(%d, %d, %d, %d,  %d, %d, %d, %d, 0x%x, %s)\n",
3144
                  srcX0, srcY0, srcX1, srcY1,
3145
                  dstX0, dstY0, dstX1, dstY1,
3146
                  mask, _mesa_lookup_enum_by_nr(filter));
3147
 
3148
   if (ctx->NewState) {
3149
      _mesa_update_state(ctx);
3150
   }
3151
 
3152
   readFb = ctx->ReadBuffer;
3153
   drawFb = ctx->DrawBuffer;
3154
 
3155
   if (!readFb || !drawFb) {
3156
      /* This will normally never happen but someday we may want to
3157
       * support MakeCurrent() with no drawables.
3158
       */
3159
      return;
3160
   }
3161
 
3162
   /* check for complete framebuffers */
3163
   if (drawFb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT ||
3164
       readFb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
3165
      _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
3166
                  "glBlitFramebufferEXT(incomplete draw/read buffers)");
3167
      return;
3168
   }
3169
 
3170
   if (!is_valid_blit_filter(ctx, filter)) {
3171
      _mesa_error(ctx, GL_INVALID_ENUM, "glBlitFramebufferEXT(%s)",
3172
                  _mesa_lookup_enum_by_nr(filter));
3173
      return;
3174
   }
3175
 
3176
   if ((filter == GL_SCALED_RESOLVE_FASTEST_EXT ||
3177
        filter == GL_SCALED_RESOLVE_NICEST_EXT) &&
3178
        (readFb->Visual.samples == 0 || drawFb->Visual.samples > 0)) {
3179
      _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebufferEXT(%s)",
3180
                  _mesa_lookup_enum_by_nr(filter));
3181
      return;
3182
   }
3183
 
3184
   if (mask & ~legalMaskBits) {
3185
      _mesa_error( ctx, GL_INVALID_VALUE, "glBlitFramebufferEXT(mask)");
3186
      return;
3187
   }
3188
 
3189
   /* depth/stencil must be blitted with nearest filtering */
3190
   if ((mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT))
3191
        && filter != GL_NEAREST) {
3192
      _mesa_error(ctx, GL_INVALID_OPERATION,
3193
             "glBlitFramebufferEXT(depth/stencil requires GL_NEAREST filter)");
3194
      return;
3195
   }
3196
 
3197
   /* get color read/draw renderbuffers */
3198
   if (mask & GL_COLOR_BUFFER_BIT) {
3199
      const GLuint numColorDrawBuffers = ctx->DrawBuffer->_NumColorDrawBuffers;
3200
      const struct gl_renderbuffer *colorReadRb = readFb->_ColorReadBuffer;
3201
      const struct gl_renderbuffer *colorDrawRb = NULL;
3202
      GLuint i;
3203
 
3204
      /* From the EXT_framebuffer_object spec:
3205
       *
3206
       *     "If a buffer is specified in  and does not exist in both
3207
       *     the read and draw framebuffers, the corresponding bit is silently
3208
       *     ignored."
3209
       */
3210
      if (!colorReadRb || numColorDrawBuffers == 0) {
3211
         mask &= ~GL_COLOR_BUFFER_BIT;
3212
      }
3213
      else {
3214
         for (i = 0; i < numColorDrawBuffers; i++) {
3215
            colorDrawRb = ctx->DrawBuffer->_ColorDrawBuffers[i];
3216
            if (!colorDrawRb)
3217
               continue;
3218
 
3219
            /* Page 193 (page 205 of the PDF) in section 4.3.2 of the OpenGL
3220
             * ES 3.0.1 spec says:
3221
             *
3222
             *     "If the source and destination buffers are identical, an
3223
             *     INVALID_OPERATION error is generated. Different mipmap
3224
             *     levels of a texture, different layers of a three-
3225
             *     dimensional texture or two-dimensional array texture, and
3226
             *     different faces of a cube map texture do not constitute
3227
             *     identical buffers."
3228
             */
3229
            if (_mesa_is_gles3(ctx) && (colorDrawRb == colorReadRb)) {
3230
               _mesa_error(ctx, GL_INVALID_OPERATION,
3231
                           "glBlitFramebuffer(source and destination color "
3232
                           "buffer cannot be the same)");
3233
               return;
3234
            }
3235
 
3236
            if (!compatible_color_datatypes(colorReadRb->Format,
3237
                                            colorDrawRb->Format)) {
3238
               _mesa_error(ctx, GL_INVALID_OPERATION,
3239
                           "glBlitFramebufferEXT(color buffer datatypes mismatch)");
3240
               return;
3241
            }
3242
            /* extra checks for multisample copies... */
3243
            if (readFb->Visual.samples > 0 || drawFb->Visual.samples > 0) {
3244
               /* color formats must match */
3245
               if (!compatible_resolve_formats(colorReadRb, colorDrawRb)) {
3246
                  _mesa_error(ctx, GL_INVALID_OPERATION,
3247
                         "glBlitFramebufferEXT(bad src/dst multisample pixel formats)");
3248
                  return;
3249
               }
3250
            }
3251
         }
3252
         if (filter != GL_NEAREST) {
3253
            /* From EXT_framebuffer_multisample_blit_scaled specification:
3254
             * "Calling BlitFramebuffer will result in an INVALID_OPERATION error
3255
             * if filter is not NEAREST and read buffer contains integer data."
3256
             */
3257
            GLenum type = _mesa_get_format_datatype(colorReadRb->Format);
3258
            if (type == GL_INT || type == GL_UNSIGNED_INT) {
3259
               _mesa_error(ctx, GL_INVALID_OPERATION,
3260
                           "glBlitFramebufferEXT(integer color type)");
3261
               return;
3262
            }
3263
         }
3264
      }
3265
   }
3266
 
3267
   if (mask & GL_STENCIL_BUFFER_BIT) {
3268
      struct gl_renderbuffer *readRb =
3269
         readFb->Attachment[BUFFER_STENCIL].Renderbuffer;
3270
      struct gl_renderbuffer *drawRb =
3271
         drawFb->Attachment[BUFFER_STENCIL].Renderbuffer;
3272
 
3273
      /* From the EXT_framebuffer_object spec:
3274
       *
3275
       *     "If a buffer is specified in  and does not exist in both
3276
       *     the read and draw framebuffers, the corresponding bit is silently
3277
       *     ignored."
3278
       */
3279
      if ((readRb == NULL) || (drawRb == NULL)) {
3280
	 mask &= ~GL_STENCIL_BUFFER_BIT;
3281
      }
3282
      else {
3283
         int read_z_bits, draw_z_bits;
3284
 
3285
         if (_mesa_is_gles3(ctx) && (drawRb == readRb)) {
3286
            _mesa_error(ctx, GL_INVALID_OPERATION,
3287
                        "glBlitFramebuffer(source and destination stencil "
3288
                        "buffer cannot be the same)");
3289
            return;
3290
         }
3291
 
3292
         if (_mesa_get_format_bits(readRb->Format, GL_STENCIL_BITS) !=
3293
             _mesa_get_format_bits(drawRb->Format, GL_STENCIL_BITS)) {
3294
            /* There is no need to check the stencil datatype here, because
3295
             * there is only one: GL_UNSIGNED_INT.
3296
             */
3297
            _mesa_error(ctx, GL_INVALID_OPERATION,
3298
                        "glBlitFramebuffer(stencil attachment format mismatch)");
3299
            return;
3300
         }
3301
 
3302
         read_z_bits = _mesa_get_format_bits(readRb->Format, GL_DEPTH_BITS);
3303
         draw_z_bits = _mesa_get_format_bits(drawRb->Format, GL_DEPTH_BITS);
3304
 
3305
         /* If both buffers also have depth data, the depth formats must match
3306
          * as well.  If one doesn't have depth, it's not blitted, so we should
3307
          * ignore the depth format check.
3308
          */
3309
         if (read_z_bits > 0 && draw_z_bits > 0 &&
3310
             (read_z_bits != draw_z_bits ||
3311
              _mesa_get_format_datatype(readRb->Format) !=
3312
              _mesa_get_format_datatype(drawRb->Format))) {
3313
 
3314
            _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebuffer"
3315
                        "(stencil attachment depth format mismatch)");
3316
            return;
3317
         }
3318
      }
3319
   }
3320
 
3321
   if (mask & GL_DEPTH_BUFFER_BIT) {
3322
      struct gl_renderbuffer *readRb =
3323
         readFb->Attachment[BUFFER_DEPTH].Renderbuffer;
3324
      struct gl_renderbuffer *drawRb =
3325
         drawFb->Attachment[BUFFER_DEPTH].Renderbuffer;
3326
 
3327
      /* From the EXT_framebuffer_object spec:
3328
       *
3329
       *     "If a buffer is specified in  and does not exist in both
3330
       *     the read and draw framebuffers, the corresponding bit is silently
3331
       *     ignored."
3332
       */
3333
      if ((readRb == NULL) || (drawRb == NULL)) {
3334
	 mask &= ~GL_DEPTH_BUFFER_BIT;
3335
      }
3336
      else {
3337
         int read_s_bit, draw_s_bit;
3338
 
3339
         if (_mesa_is_gles3(ctx) && (drawRb == readRb)) {
3340
            _mesa_error(ctx, GL_INVALID_OPERATION,
3341
                        "glBlitFramebuffer(source and destination depth "
3342
                        "buffer cannot be the same)");
3343
            return;
3344
         }
3345
 
3346
         if ((_mesa_get_format_bits(readRb->Format, GL_DEPTH_BITS) !=
3347
              _mesa_get_format_bits(drawRb->Format, GL_DEPTH_BITS)) ||
3348
             (_mesa_get_format_datatype(readRb->Format) !=
3349
              _mesa_get_format_datatype(drawRb->Format))) {
3350
            _mesa_error(ctx, GL_INVALID_OPERATION,
3351
                        "glBlitFramebuffer(depth attachment format mismatch)");
3352
            return;
3353
         }
3354
 
3355
         read_s_bit = _mesa_get_format_bits(readRb->Format, GL_STENCIL_BITS);
3356
         draw_s_bit = _mesa_get_format_bits(drawRb->Format, GL_STENCIL_BITS);
3357
 
3358
         /* If both buffers also have stencil data, the stencil formats must
3359
          * match as well.  If one doesn't have stencil, it's not blitted, so
3360
          * we should ignore the stencil format check.
3361
          */
3362
         if (read_s_bit > 0 && draw_s_bit > 0 && read_s_bit != draw_s_bit) {
3363
            _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebuffer"
3364
                        "(depth attachment stencil bits mismatch)");
3365
            return;
3366
         }
3367
      }
3368
   }
3369
 
3370
 
3371
   if (_mesa_is_gles3(ctx)) {
3372
      /* Page 194 (page 206 of the PDF) in section 4.3.2 of the OpenGL ES
3373
       * 3.0.1 spec says:
3374
       *
3375
       *     "If SAMPLE_BUFFERS for the draw framebuffer is greater than zero,
3376
       *     an INVALID_OPERATION error is generated."
3377
       */
3378
      if (drawFb->Visual.samples > 0) {
3379
         _mesa_error(ctx, GL_INVALID_OPERATION,
3380
                     "glBlitFramebuffer(destination samples must be 0)");
3381
         return;
3382
      }
3383
 
3384
      /* Page 194 (page 206 of the PDF) in section 4.3.2 of the OpenGL ES
3385
       * 3.0.1 spec says:
3386
       *
3387
       *     "If SAMPLE_BUFFERS for the read framebuffer is greater than zero,
3388
       *     no copy is performed and an INVALID_OPERATION error is generated
3389
       *     if the formats of the read and draw framebuffers are not
3390
       *     identical or if the source and destination rectangles are not
3391
       *     defined with the same (X0, Y0) and (X1, Y1) bounds."
3392
       *
3393
       * The format check was made above because desktop OpenGL has the same
3394
       * requirement.
3395
       */
3396
      if (readFb->Visual.samples > 0
3397
          && (srcX0 != dstX0 || srcY0 != dstY0
3398
              || srcX1 != dstX1 || srcY1 != dstY1)) {
3399
         _mesa_error(ctx, GL_INVALID_OPERATION,
3400
                     "glBlitFramebuffer(bad src/dst multisample region)");
3401
         return;
3402
      }
3403
   } else {
3404
      if (readFb->Visual.samples > 0 &&
3405
          drawFb->Visual.samples > 0 &&
3406
          readFb->Visual.samples != drawFb->Visual.samples) {
3407
         _mesa_error(ctx, GL_INVALID_OPERATION,
3408
                     "glBlitFramebufferEXT(mismatched samples)");
3409
         return;
3410
      }
3411
 
3412
      /* extra checks for multisample copies... */
3413
      if ((readFb->Visual.samples > 0 || drawFb->Visual.samples > 0) &&
3414
          (filter == GL_NEAREST || filter == GL_LINEAR)) {
3415
         /* src and dest region sizes must be the same */
3416
         if (abs(srcX1 - srcX0) != abs(dstX1 - dstX0) ||
3417
             abs(srcY1 - srcY0) != abs(dstY1 - dstY0)) {
3418
            _mesa_error(ctx, GL_INVALID_OPERATION,
3419
                        "glBlitFramebufferEXT(bad src/dst multisample region sizes)");
3420
            return;
3421
         }
3422
      }
3423
   }
3424
 
3425
   if (!ctx->Extensions.EXT_framebuffer_blit) {
3426
      _mesa_error(ctx, GL_INVALID_OPERATION, "glBlitFramebufferEXT");
3427
      return;
3428
   }
3429
 
3430
   /* Debug code */
3431
   if (DEBUG_BLIT) {
3432
      const struct gl_renderbuffer *colorReadRb = readFb->_ColorReadBuffer;
3433
      const struct gl_renderbuffer *colorDrawRb = NULL;
3434
      GLuint i = 0;
3435
 
3436
      printf("glBlitFramebuffer(%d, %d, %d, %d,  %d, %d, %d, %d,"
3437
	     " 0x%x, 0x%x)\n",
3438
	     srcX0, srcY0, srcX1, srcY1,
3439
	     dstX0, dstY0, dstX1, dstY1,
3440
	     mask, filter);
3441
      if (colorReadRb) {
3442
         const struct gl_renderbuffer_attachment *att;
3443
 
3444
         att = find_attachment(readFb, colorReadRb);
3445
         printf("  Src FBO %u  RB %u (%dx%d)  ",
3446
		readFb->Name, colorReadRb->Name,
3447
		colorReadRb->Width, colorReadRb->Height);
3448
         if (att && att->Texture) {
3449
            printf("Tex %u  tgt 0x%x  level %u  face %u",
3450
		   att->Texture->Name,
3451
		   att->Texture->Target,
3452
		   att->TextureLevel,
3453
		   att->CubeMapFace);
3454
         }
3455
         printf("\n");
3456
 
3457
         /* Print all active color render buffers */
3458
         for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) {
3459
            colorDrawRb = ctx->DrawBuffer->_ColorDrawBuffers[i];
3460
            if (!colorDrawRb)
3461
               continue;
3462
 
3463
            att = find_attachment(drawFb, colorDrawRb);
3464
            printf("  Dst FBO %u  RB %u (%dx%d)  ",
3465
		   drawFb->Name, colorDrawRb->Name,
3466
		   colorDrawRb->Width, colorDrawRb->Height);
3467
            if (att && att->Texture) {
3468
               printf("Tex %u  tgt 0x%x  level %u  face %u",
3469
		      att->Texture->Name,
3470
		      att->Texture->Target,
3471
		      att->TextureLevel,
3472
		      att->CubeMapFace);
3473
            }
3474
            printf("\n");
3475
         }
3476
      }
3477
   }
3478
 
3479
   if (!mask ||
3480
       (srcX1 - srcX0) == 0 || (srcY1 - srcY0) == 0 ||
3481
       (dstX1 - dstX0) == 0 || (dstY1 - dstY0) == 0) {
3482
      return;
3483
   }
3484
 
3485
   ASSERT(ctx->Driver.BlitFramebuffer);
3486
   ctx->Driver.BlitFramebuffer(ctx,
3487
                               srcX0, srcY0, srcX1, srcY1,
3488
                               dstX0, dstY0, dstX1, dstY1,
3489
                               mask, filter);
3490
}
3491
 
3492
 
3493
static void
3494
invalidate_framebuffer_storage(GLenum target, GLsizei numAttachments,
3495
                               const GLenum *attachments, GLint x, GLint y,
3496
                               GLsizei width, GLsizei height, const char *name)
3497
{
3498
   int i;
3499
   struct gl_framebuffer *fb;
3500
   GET_CURRENT_CONTEXT(ctx);
3501
 
3502
   fb = get_framebuffer_target(ctx, target);
3503
   if (!fb) {
3504
      _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", name);
3505
      return;
3506
   }
3507
 
3508
   if (numAttachments < 0) {
3509
      _mesa_error(ctx, GL_INVALID_VALUE,
3510
                  "%s(numAttachments < 0)", name);
3511
      return;
3512
   }
3513
 
3514
   /* The GL_ARB_invalidate_subdata spec says:
3515
    *
3516
    *     "If an attachment is specified that does not exist in the
3517
    *     framebuffer bound to , it is ignored."
3518
    *
3519
    * It also says:
3520
    *
3521
    *     "If  contains COLOR_ATTACHMENTm and m is greater than
3522
    *     or equal to the value of MAX_COLOR_ATTACHMENTS, then the error
3523
    *     INVALID_OPERATION is generated."
3524
    *
3525
    * No mention is made of GL_AUXi being out of range.  Therefore, we allow
3526
    * any enum that can be allowed by the API (OpenGL ES 3.0 has a different
3527
    * set of retrictions).
3528
    */
3529
   for (i = 0; i < numAttachments; i++) {
3530
      if (_mesa_is_winsys_fbo(fb)) {
3531
         switch (attachments[i]) {
3532
         case GL_ACCUM:
3533
         case GL_AUX0:
3534
         case GL_AUX1:
3535
         case GL_AUX2:
3536
         case GL_AUX3:
3537
            /* Accumulation buffers and auxilary buffers were removed in
3538
             * OpenGL 3.1, and they never existed in OpenGL ES.
3539
             */
3540
            if (ctx->API != API_OPENGL_COMPAT)
3541
               goto invalid_enum;
3542
            break;
3543
         case GL_COLOR:
3544
         case GL_DEPTH:
3545
         case GL_STENCIL:
3546
            break;
3547
         case GL_BACK_LEFT:
3548
         case GL_BACK_RIGHT:
3549
         case GL_FRONT_LEFT:
3550
         case GL_FRONT_RIGHT:
3551
            if (!_mesa_is_desktop_gl(ctx))
3552
               goto invalid_enum;
3553
            break;
3554
         default:
3555
            goto invalid_enum;
3556
         }
3557
      } else {
3558
         switch (attachments[i]) {
3559
         case GL_DEPTH_ATTACHMENT:
3560
         case GL_STENCIL_ATTACHMENT:
3561
            break;
3562
         case GL_COLOR_ATTACHMENT0:
3563
         case GL_COLOR_ATTACHMENT1:
3564
         case GL_COLOR_ATTACHMENT2:
3565
         case GL_COLOR_ATTACHMENT3:
3566
         case GL_COLOR_ATTACHMENT4:
3567
         case GL_COLOR_ATTACHMENT5:
3568
         case GL_COLOR_ATTACHMENT6:
3569
         case GL_COLOR_ATTACHMENT7:
3570
         case GL_COLOR_ATTACHMENT8:
3571
         case GL_COLOR_ATTACHMENT9:
3572
         case GL_COLOR_ATTACHMENT10:
3573
         case GL_COLOR_ATTACHMENT11:
3574
         case GL_COLOR_ATTACHMENT12:
3575
         case GL_COLOR_ATTACHMENT13:
3576
         case GL_COLOR_ATTACHMENT14:
3577
         case GL_COLOR_ATTACHMENT15: {
3578
            unsigned k = attachments[i] - GL_COLOR_ATTACHMENT0;
3579
            if (k >= ctx->Const.MaxColorAttachments) {
3580
               _mesa_error(ctx, GL_INVALID_OPERATION,
3581
                           "%s(attachment >= max. color attachments)", name);
3582
               return;
3583
            }
3584
            break;
3585
         }
3586
         default:
3587
            goto invalid_enum;
3588
         }
3589
      }
3590
   }
3591
 
3592
   /* We don't actually do anything for this yet.  Just return after
3593
    * validating the parameters and generating the required errors.
3594
    */
3595
   return;
3596
 
3597
invalid_enum:
3598
   _mesa_error(ctx, GL_INVALID_ENUM, "%s(attachment)", name);
3599
   return;
3600
}
3601
 
3602
void GLAPIENTRY
3603
_mesa_InvalidateSubFramebuffer(GLenum target, GLsizei numAttachments,
3604
                               const GLenum *attachments, GLint x, GLint y,
3605
                               GLsizei width, GLsizei height)
3606
{
3607
   invalidate_framebuffer_storage(target, numAttachments, attachments,
3608
                                  x, y, width, height,
3609
                                  "glInvalidateSubFramebuffer");
3610
}
3611
 
3612
void GLAPIENTRY
3613
_mesa_InvalidateFramebuffer(GLenum target, GLsizei numAttachments,
3614
                            const GLenum *attachments)
3615
{
3616
   /* The GL_ARB_invalidate_subdata spec says:
3617
    *
3618
    *     "The command
3619
    *
3620
    *        void InvalidateFramebuffer(enum target,
3621
    *                                   sizei numAttachments,
3622
    *                                   const enum *attachments);
3623
    *
3624
    *     is equivalent to the command InvalidateSubFramebuffer with , ,
3625
    *     ,  equal to 0, 0, ,
3626
    *      respectively."
3627
    */
3628
   invalidate_framebuffer_storage(target, numAttachments, attachments,
3629
                                  0, 0, MAX_VIEWPORT_WIDTH, MAX_VIEWPORT_HEIGHT,
3630
                                  "glInvalidateFramebuffer");
3631
}
3632
 
3633
void GLAPIENTRY
3634
_mesa_DiscardFramebufferEXT(GLenum target, GLsizei numAttachments,
3635
                            const GLenum *attachments)
3636
{
3637
   struct gl_framebuffer *fb;
3638
   GLint i;
3639
 
3640
   GET_CURRENT_CONTEXT(ctx);
3641
 
3642
   fb = get_framebuffer_target(ctx, target);
3643
   if (!fb) {
3644
      _mesa_error(ctx, GL_INVALID_ENUM,
3645
         "glDiscardFramebufferEXT(target %s)",
3646
         _mesa_lookup_enum_by_nr(target));
3647
      return;
3648
   }
3649
 
3650
   if (numAttachments < 0) {
3651
      _mesa_error(ctx, GL_INVALID_VALUE,
3652
                  "glDiscardFramebufferEXT(numAttachments < 0)");
3653
      return;
3654
   }
3655
 
3656
   for (i = 0; i < numAttachments; i++) {
3657
      switch (attachments[i]) {
3658
      case GL_COLOR:
3659
      case GL_DEPTH:
3660
      case GL_STENCIL:
3661
         if (_mesa_is_user_fbo(fb))
3662
            goto invalid_enum;
3663
         break;
3664
      case GL_COLOR_ATTACHMENT0:
3665
      case GL_DEPTH_ATTACHMENT:
3666
      case GL_STENCIL_ATTACHMENT:
3667
         if (_mesa_is_winsys_fbo(fb))
3668
            goto invalid_enum;
3669
         break;
3670
      default:
3671
         goto invalid_enum;
3672
      }
3673
   }
3674
 
3675
   if (ctx->Driver.DiscardFramebuffer)
3676
      ctx->Driver.DiscardFramebuffer(ctx, target, numAttachments, attachments);
3677
 
3678
   return;
3679
 
3680
invalid_enum:
3681
   _mesa_error(ctx, GL_INVALID_ENUM,
3682
               "glDiscardFramebufferEXT(attachment %s)",
3683
              _mesa_lookup_enum_by_nr(attachments[i]));
3684
}