intel_fbo.c revision 2e5a1a254ed81b1d3efa6064f48183eefac784d0
1/**************************************************************************
2 *
3 * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28
29#include "main/imports.h"
30#include "main/macros.h"
31#include "main/mfeatures.h"
32#include "main/mtypes.h"
33#include "main/fbobject.h"
34#include "main/framebuffer.h"
35#include "main/renderbuffer.h"
36#include "main/context.h"
37#include "main/teximage.h"
38#include "swrast/swrast.h"
39#include "drivers/common/meta.h"
40
41#include "intel_context.h"
42#include "intel_batchbuffer.h"
43#include "intel_buffers.h"
44#include "intel_fbo.h"
45#include "intel_mipmap_tree.h"
46#include "intel_regions.h"
47#include "intel_tex.h"
48#include "intel_span.h"
49#ifndef I915
50#include "brw_context.h"
51#endif
52
53#define FILE_DEBUG_FLAG DEBUG_FBO
54
55
56/**
57 * Create a new framebuffer object.
58 */
59static struct gl_framebuffer *
60intel_new_framebuffer(struct gl_context * ctx, GLuint name)
61{
62   /* Only drawable state in intel_framebuffer at this time, just use Mesa's
63    * class
64    */
65   return _mesa_new_framebuffer(ctx, name);
66}
67
68
69/** Called by gl_renderbuffer::Delete() */
70static void
71intel_delete_renderbuffer(struct gl_renderbuffer *rb)
72{
73   struct intel_renderbuffer *irb = intel_renderbuffer(rb);
74
75   ASSERT(irb);
76
77   intel_region_release(&irb->region);
78   intel_region_release(&irb->hiz_region);
79
80   _mesa_reference_renderbuffer(&irb->wrapped_depth, NULL);
81   _mesa_reference_renderbuffer(&irb->wrapped_stencil, NULL);
82
83   free(irb);
84}
85
86
87/**
88 * Return a pointer to a specific pixel in a renderbuffer.
89 */
90static void *
91intel_get_pointer(struct gl_context * ctx, struct gl_renderbuffer *rb,
92                  GLint x, GLint y)
93{
94   /* By returning NULL we force all software rendering to go through
95    * the span routines.
96    */
97   return NULL;
98}
99
100
101/**
102 * Called via glRenderbufferStorageEXT() to set the format and allocate
103 * storage for a user-created renderbuffer.
104 */
105GLboolean
106intel_alloc_renderbuffer_storage(struct gl_context * ctx, struct gl_renderbuffer *rb,
107                                 GLenum internalFormat,
108                                 GLuint width, GLuint height)
109{
110   struct intel_context *intel = intel_context(ctx);
111   struct intel_renderbuffer *irb = intel_renderbuffer(rb);
112   int cpp, tiling;
113
114   ASSERT(rb->Name != 0);
115
116   switch (internalFormat) {
117   default:
118      /* Use the same format-choice logic as for textures.
119       * Renderbuffers aren't any different from textures for us,
120       * except they're less useful because you can't texture with
121       * them.
122       */
123      rb->Format = intel->ctx.Driver.ChooseTextureFormat(ctx, internalFormat,
124							 GL_NONE, GL_NONE);
125      break;
126   case GL_STENCIL_INDEX:
127   case GL_STENCIL_INDEX1_EXT:
128   case GL_STENCIL_INDEX4_EXT:
129   case GL_STENCIL_INDEX8_EXT:
130   case GL_STENCIL_INDEX16_EXT:
131      /* These aren't actual texture formats, so force them here. */
132      if (intel->has_separate_stencil) {
133	 rb->Format = MESA_FORMAT_S8;
134      } else {
135	 assert(!intel->must_use_separate_stencil);
136	 rb->Format = MESA_FORMAT_S8_Z24;
137      }
138      break;
139   }
140
141   rb->Width = width;
142   rb->Height = height;
143   rb->_BaseFormat = _mesa_base_fbo_format(ctx, internalFormat);
144   rb->DataType = intel_mesa_format_to_rb_datatype(rb->Format);
145   cpp = _mesa_get_format_bytes(rb->Format);
146
147   intel_flush(ctx);
148
149   /* free old region */
150   if (irb->region) {
151      intel_region_release(&irb->region);
152   }
153   if (irb->hiz_region) {
154      intel_region_release(&irb->hiz_region);
155   }
156
157   /* allocate new memory region/renderbuffer */
158
159   /* alloc hardware renderbuffer */
160   DBG("Allocating %d x %d Intel RBO\n", width, height);
161
162   tiling = I915_TILING_NONE;
163   if (intel->use_texture_tiling) {
164      GLenum base_format = _mesa_get_format_base_format(rb->Format);
165
166      if (intel->gen >= 4 && (base_format == GL_DEPTH_COMPONENT ||
167			      base_format == GL_STENCIL_INDEX ||
168			      base_format == GL_DEPTH_STENCIL))
169	 tiling = I915_TILING_Y;
170      else
171	 tiling = I915_TILING_X;
172   }
173
174   if (irb->Base.Format == MESA_FORMAT_S8) {
175      /*
176       * The stencil buffer is W tiled. However, we request from the kernel a
177       * non-tiled buffer because the GTT is incapable of W fencing.
178       *
179       * The stencil buffer has quirky pitch requirements.  From Vol 2a,
180       * 11.5.6.2.1 3DSTATE_STENCIL_BUFFER, field "Surface Pitch":
181       *    The pitch must be set to 2x the value computed based on width, as
182       *    the stencil buffer is stored with two rows interleaved.
183       * To accomplish this, we resort to the nasty hack of doubling the drm
184       * region's cpp and halving its height.
185       *
186       * If we neglect to double the pitch, then render corruption occurs.
187       */
188      irb->region = intel_region_alloc(intel->intelScreen,
189				       I915_TILING_NONE,
190				       cpp * 2,
191				       ALIGN(width, 64),
192				       ALIGN((height + 1) / 2, 64),
193				       true);
194      if (!irb->region)
195	return false;
196
197   } else if (irb->Base.Format == MESA_FORMAT_S8_Z24
198	      && intel->must_use_separate_stencil) {
199
200      bool ok = true;
201      struct gl_renderbuffer *depth_rb;
202      struct gl_renderbuffer *stencil_rb;
203
204      depth_rb = intel_create_wrapped_renderbuffer(ctx, width, height,
205						   MESA_FORMAT_X8_Z24);
206      stencil_rb = intel_create_wrapped_renderbuffer(ctx, width, height,
207						     MESA_FORMAT_S8);
208      ok = depth_rb && stencil_rb;
209      ok = ok && intel_alloc_renderbuffer_storage(ctx, depth_rb,
210						  depth_rb->InternalFormat,
211						  width, height);
212      ok = ok && intel_alloc_renderbuffer_storage(ctx, stencil_rb,
213						  stencil_rb->InternalFormat,
214						  width, height);
215
216      if (!ok) {
217	 if (depth_rb) {
218	    intel_delete_renderbuffer(depth_rb);
219	 }
220	 if (stencil_rb) {
221	    intel_delete_renderbuffer(stencil_rb);
222	 }
223	 return false;
224      }
225
226      depth_rb->Wrapped = rb;
227      stencil_rb->Wrapped = rb;
228      _mesa_reference_renderbuffer(&irb->wrapped_depth, depth_rb);
229      _mesa_reference_renderbuffer(&irb->wrapped_stencil, stencil_rb);
230
231   } else {
232      irb->region = intel_region_alloc(intel->intelScreen, tiling, cpp,
233				       width, height, true);
234      if (!irb->region)
235	 return false;
236
237      if (intel->vtbl.is_hiz_depth_format(intel, rb->Format)) {
238	 irb->hiz_region = intel_region_alloc(intel->intelScreen,
239					      I915_TILING_Y,
240					      irb->region->cpp,
241					      irb->region->width,
242					      irb->region->height,
243					      true);
244	 if (!irb->hiz_region) {
245	    intel_region_release(&irb->region);
246	    return false;
247	 }
248      }
249   }
250
251   return true;
252}
253
254
255#if FEATURE_OES_EGL_image
256static void
257intel_image_target_renderbuffer_storage(struct gl_context *ctx,
258					struct gl_renderbuffer *rb,
259					void *image_handle)
260{
261   struct intel_context *intel = intel_context(ctx);
262   struct intel_renderbuffer *irb;
263   __DRIscreen *screen;
264   __DRIimage *image;
265
266   screen = intel->intelScreen->driScrnPriv;
267   image = screen->dri2.image->lookupEGLImage(screen, image_handle,
268					      screen->loaderPrivate);
269   if (image == NULL)
270      return;
271
272   /* __DRIimage is opaque to the core so it has to be checked here */
273   switch (image->format) {
274   case MESA_FORMAT_RGBA8888_REV:
275      _mesa_error(&intel->ctx, GL_INVALID_OPERATION,
276            "glEGLImageTargetRenderbufferStorage(unsupported image format");
277      return;
278      break;
279   default:
280      break;
281   }
282
283   irb = intel_renderbuffer(rb);
284   intel_region_reference(&irb->region, image->region);
285
286   rb->InternalFormat = image->internal_format;
287   rb->Width = image->region->width;
288   rb->Height = image->region->height;
289   rb->Format = image->format;
290   rb->DataType = image->data_type;
291   rb->_BaseFormat = _mesa_base_fbo_format(&intel->ctx,
292					   image->internal_format);
293}
294#endif
295
296/**
297 * Called for each hardware renderbuffer when a _window_ is resized.
298 * Just update fields.
299 * Not used for user-created renderbuffers!
300 */
301static GLboolean
302intel_alloc_window_storage(struct gl_context * ctx, struct gl_renderbuffer *rb,
303                           GLenum internalFormat, GLuint width, GLuint height)
304{
305   ASSERT(rb->Name == 0);
306   rb->Width = width;
307   rb->Height = height;
308   rb->InternalFormat = internalFormat;
309
310   return true;
311}
312
313
314static void
315intel_resize_buffers(struct gl_context *ctx, struct gl_framebuffer *fb,
316		     GLuint width, GLuint height)
317{
318   int i;
319
320   _mesa_resize_framebuffer(ctx, fb, width, height);
321
322   fb->Initialized = true; /* XXX remove someday */
323
324   if (fb->Name != 0) {
325      return;
326   }
327
328
329   /* Make sure all window system renderbuffers are up to date */
330   for (i = BUFFER_FRONT_LEFT; i <= BUFFER_BACK_RIGHT; i++) {
331      struct gl_renderbuffer *rb = fb->Attachment[i].Renderbuffer;
332
333      /* only resize if size is changing */
334      if (rb && (rb->Width != width || rb->Height != height)) {
335	 rb->AllocStorage(ctx, rb, rb->InternalFormat, width, height);
336      }
337   }
338}
339
340
341/** Dummy function for gl_renderbuffer::AllocStorage() */
342static GLboolean
343intel_nop_alloc_storage(struct gl_context * ctx, struct gl_renderbuffer *rb,
344                        GLenum internalFormat, GLuint width, GLuint height)
345{
346   _mesa_problem(ctx, "intel_op_alloc_storage should never be called.");
347   return false;
348}
349
350/**
351 * Create a new intel_renderbuffer which corresponds to an on-screen window,
352 * not a user-created renderbuffer.
353 */
354struct intel_renderbuffer *
355intel_create_renderbuffer(gl_format format)
356{
357   GET_CURRENT_CONTEXT(ctx);
358
359   struct intel_renderbuffer *irb;
360
361   irb = CALLOC_STRUCT(intel_renderbuffer);
362   if (!irb) {
363      _mesa_error(ctx, GL_OUT_OF_MEMORY, "creating renderbuffer");
364      return NULL;
365   }
366
367   _mesa_init_renderbuffer(&irb->Base, 0);
368   irb->Base.ClassID = INTEL_RB_CLASS;
369   irb->Base._BaseFormat = _mesa_get_format_base_format(format);
370   irb->Base.Format = format;
371   irb->Base.InternalFormat = irb->Base._BaseFormat;
372   irb->Base.DataType = intel_mesa_format_to_rb_datatype(format);
373
374   /* intel-specific methods */
375   irb->Base.Delete = intel_delete_renderbuffer;
376   irb->Base.AllocStorage = intel_alloc_window_storage;
377   irb->Base.GetPointer = intel_get_pointer;
378
379   return irb;
380}
381
382
383struct gl_renderbuffer*
384intel_create_wrapped_renderbuffer(struct gl_context * ctx,
385				  int width, int height,
386				  gl_format format)
387{
388   /*
389    * The name here is irrelevant, as long as its nonzero, because the
390    * renderbuffer never gets entered into Mesa's renderbuffer hash table.
391    */
392   GLuint name = ~0;
393
394   struct intel_renderbuffer *irb = CALLOC_STRUCT(intel_renderbuffer);
395   if (!irb) {
396      _mesa_error(ctx, GL_OUT_OF_MEMORY, "creating renderbuffer");
397      return NULL;
398   }
399
400   struct gl_renderbuffer *rb = &irb->Base;
401   _mesa_init_renderbuffer(rb, name);
402   rb->ClassID = INTEL_RB_CLASS;
403   rb->_BaseFormat = _mesa_get_format_base_format(format);
404   rb->Format = format;
405   rb->InternalFormat = rb->_BaseFormat;
406   rb->DataType = intel_mesa_format_to_rb_datatype(format);
407   rb->Width = width;
408   rb->Height = height;
409
410   return rb;
411}
412
413
414/**
415 * Create a new renderbuffer object.
416 * Typically called via glBindRenderbufferEXT().
417 */
418static struct gl_renderbuffer *
419intel_new_renderbuffer(struct gl_context * ctx, GLuint name)
420{
421   /*struct intel_context *intel = intel_context(ctx); */
422   struct intel_renderbuffer *irb;
423
424   irb = CALLOC_STRUCT(intel_renderbuffer);
425   if (!irb) {
426      _mesa_error(ctx, GL_OUT_OF_MEMORY, "creating renderbuffer");
427      return NULL;
428   }
429
430   _mesa_init_renderbuffer(&irb->Base, name);
431   irb->Base.ClassID = INTEL_RB_CLASS;
432
433   /* intel-specific methods */
434   irb->Base.Delete = intel_delete_renderbuffer;
435   irb->Base.AllocStorage = intel_alloc_renderbuffer_storage;
436   irb->Base.GetPointer = intel_get_pointer;
437   /* span routines set in alloc_storage function */
438
439   return &irb->Base;
440}
441
442
443/**
444 * Called via glBindFramebufferEXT().
445 */
446static void
447intel_bind_framebuffer(struct gl_context * ctx, GLenum target,
448                       struct gl_framebuffer *fb, struct gl_framebuffer *fbread)
449{
450   if (target == GL_FRAMEBUFFER_EXT || target == GL_DRAW_FRAMEBUFFER_EXT) {
451      intel_draw_buffer(ctx);
452   }
453   else {
454      /* don't need to do anything if target == GL_READ_FRAMEBUFFER_EXT */
455   }
456}
457
458
459/**
460 * Called via glFramebufferRenderbufferEXT().
461 */
462static void
463intel_framebuffer_renderbuffer(struct gl_context * ctx,
464                               struct gl_framebuffer *fb,
465                               GLenum attachment, struct gl_renderbuffer *rb)
466{
467   DBG("Intel FramebufferRenderbuffer %u %u\n", fb->Name, rb ? rb->Name : 0);
468
469   intel_flush(ctx);
470
471   _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb);
472   intel_draw_buffer(ctx);
473}
474
475static bool
476intel_update_tex_wrapper_regions(struct intel_context *intel,
477				 struct intel_renderbuffer *irb,
478				 struct intel_texture_image *intel_image);
479
480static bool
481intel_update_wrapper(struct gl_context *ctx, struct intel_renderbuffer *irb,
482		     struct gl_texture_image *texImage)
483{
484   struct intel_context *intel = intel_context(ctx);
485   struct intel_texture_image *intel_image = intel_texture_image(texImage);
486   int width, height, depth;
487
488   if (!intel_span_supports_format(texImage->TexFormat)) {
489      DBG("Render to texture BAD FORMAT %s\n",
490	  _mesa_get_format_name(texImage->TexFormat));
491      return false;
492   } else {
493      DBG("Render to texture %s\n", _mesa_get_format_name(texImage->TexFormat));
494   }
495
496   intel_miptree_get_dimensions_for_image(texImage, &width, &height, &depth);
497
498   irb->Base.Format = texImage->TexFormat;
499   irb->Base.DataType = intel_mesa_format_to_rb_datatype(texImage->TexFormat);
500   irb->Base.InternalFormat = texImage->InternalFormat;
501   irb->Base._BaseFormat = _mesa_base_tex_format(ctx, irb->Base.InternalFormat);
502   irb->Base.Width = width;
503   irb->Base.Height = height;
504
505   irb->Base.Delete = intel_delete_renderbuffer;
506   irb->Base.AllocStorage = intel_nop_alloc_storage;
507
508   if (intel_image->stencil_rb) {
509      /*  The tex image has packed depth/stencil format, but is using separate
510       * stencil. */
511
512      bool ok;
513      struct intel_renderbuffer *depth_irb =
514	 intel_renderbuffer(intel_image->depth_rb);
515
516      /* Update the hiz region if necessary. */
517      ok =  intel_update_tex_wrapper_regions(intel, depth_irb, intel_image);
518      if (!ok) {
519	 return false;
520      }
521
522      /* The tex image shares its embedded depth and stencil renderbuffers with
523       * the renderbuffer wrapper. */
524      _mesa_reference_renderbuffer(&irb->wrapped_depth,
525				   intel_image->depth_rb);
526      _mesa_reference_renderbuffer(&irb->wrapped_stencil,
527				   intel_image->stencil_rb);
528
529      return true;
530   } else {
531      return intel_update_tex_wrapper_regions(intel, irb, intel_image);
532   }
533}
534
535/**
536 * FIXME: The handling of the hiz region is broken for mipmapped depth textures
537 * FIXME: because intel_finalize_mipmap_tree is unaware of it.
538 */
539static bool
540intel_update_tex_wrapper_regions(struct intel_context *intel,
541				 struct intel_renderbuffer *irb,
542				 struct intel_texture_image *intel_image)
543{
544   struct gl_renderbuffer *rb = &irb->Base;
545
546   /* Point the renderbuffer's region to the texture's region. */
547   if (irb->region != intel_image->mt->region) {
548      intel_region_reference(&irb->region, intel_image->mt->region);
549   }
550
551   /* Allocate the texture's hiz region if necessary. */
552   if (intel->vtbl.is_hiz_depth_format(intel, rb->Format)
553       && !intel_image->mt->hiz_region) {
554      intel_image->mt->hiz_region =
555         intel_region_alloc(intel->intelScreen,
556                            I915_TILING_Y,
557                            _mesa_get_format_bytes(rb->Format),
558                            rb->Width,
559                            rb->Height,
560                            true);
561      if (!intel_image->mt->hiz_region)
562         return false;
563   }
564
565   /* Point the renderbuffer's hiz region to the texture's hiz region. */
566   if (irb->hiz_region != intel_image->mt->hiz_region) {
567      intel_region_reference(&irb->hiz_region, intel_image->mt->hiz_region);
568   }
569
570   return true;
571}
572
573
574/**
575 * When glFramebufferTexture[123]D is called this function sets up the
576 * gl_renderbuffer wrapper around the texture image.
577 * This will have the region info needed for hardware rendering.
578 */
579static struct intel_renderbuffer *
580intel_wrap_texture(struct gl_context * ctx, struct gl_texture_image *texImage)
581{
582   const GLuint name = ~0;   /* not significant, but distinct for debugging */
583   struct intel_renderbuffer *irb;
584
585   /* make an intel_renderbuffer to wrap the texture image */
586   irb = CALLOC_STRUCT(intel_renderbuffer);
587   if (!irb) {
588      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glFramebufferTexture");
589      return NULL;
590   }
591
592   _mesa_init_renderbuffer(&irb->Base, name);
593   irb->Base.ClassID = INTEL_RB_CLASS;
594
595   if (!intel_update_wrapper(ctx, irb, texImage)) {
596      free(irb);
597      return NULL;
598   }
599
600   return irb;
601}
602
603void
604intel_renderbuffer_set_draw_offset(struct intel_renderbuffer *irb,
605				   struct intel_texture_image *intel_image,
606				   int zoffset)
607{
608   unsigned int dst_x, dst_y;
609
610   /* compute offset of the particular 2D image within the texture region */
611   intel_miptree_get_image_offset(intel_image->mt,
612				  intel_image->base.Base.Level,
613				  intel_image->base.Base.Face,
614				  zoffset,
615				  &dst_x, &dst_y);
616
617   irb->draw_x = dst_x;
618   irb->draw_y = dst_y;
619}
620
621/**
622 * Rendering to tiled buffers requires that the base address of the
623 * buffer be aligned to a page boundary.  We generally render to
624 * textures by pointing the surface at the mipmap image level, which
625 * may not be aligned to a tile boundary.
626 *
627 * This function returns an appropriately-aligned base offset
628 * according to the tiling restrictions, plus any required x/y offset
629 * from there.
630 */
631uint32_t
632intel_renderbuffer_tile_offsets(struct intel_renderbuffer *irb,
633				uint32_t *tile_x,
634				uint32_t *tile_y)
635{
636   int cpp = irb->region->cpp;
637   uint32_t pitch = irb->region->pitch * cpp;
638
639   if (irb->region->tiling == I915_TILING_NONE) {
640      *tile_x = 0;
641      *tile_y = 0;
642      return irb->draw_x * cpp + irb->draw_y * pitch;
643   } else if (irb->region->tiling == I915_TILING_X) {
644      *tile_x = irb->draw_x % (512 / cpp);
645      *tile_y = irb->draw_y % 8;
646      return ((irb->draw_y / 8) * (8 * pitch) +
647	      (irb->draw_x - *tile_x) / (512 / cpp) * 4096);
648   } else {
649      assert(irb->region->tiling == I915_TILING_Y);
650      *tile_x = irb->draw_x % (128 / cpp);
651      *tile_y = irb->draw_y % 32;
652      return ((irb->draw_y / 32) * (32 * pitch) +
653	      (irb->draw_x - *tile_x) / (128 / cpp) * 4096);
654   }
655}
656
657#ifndef I915
658static bool
659need_tile_offset_workaround(struct brw_context *brw,
660			    struct intel_renderbuffer *irb)
661{
662   uint32_t tile_x, tile_y;
663
664   if (brw->has_surface_tile_offset)
665      return false;
666
667   intel_renderbuffer_tile_offsets(irb, &tile_x, &tile_y);
668
669   return tile_x != 0 || tile_y != 0;
670}
671#endif
672
673/**
674 * Called by glFramebufferTexture[123]DEXT() (and other places) to
675 * prepare for rendering into texture memory.  This might be called
676 * many times to choose different texture levels, cube faces, etc
677 * before intel_finish_render_texture() is ever called.
678 */
679static void
680intel_render_texture(struct gl_context * ctx,
681                     struct gl_framebuffer *fb,
682                     struct gl_renderbuffer_attachment *att)
683{
684   struct gl_texture_image *image = _mesa_get_attachment_teximage(att);
685   struct intel_renderbuffer *irb = intel_renderbuffer(att->Renderbuffer);
686   struct intel_texture_image *intel_image = intel_texture_image(image);
687
688   (void) fb;
689
690   if (!intel_image->mt) {
691      /* Fallback on drawing to a texture that doesn't have a miptree
692       * (has a border, width/height 0, etc.)
693       */
694      _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
695      _swrast_render_texture(ctx, fb, att);
696      return;
697   }
698   else if (!irb) {
699      irb = intel_wrap_texture(ctx, image);
700      if (irb) {
701         /* bind the wrapper to the attachment point */
702         _mesa_reference_renderbuffer(&att->Renderbuffer, &irb->Base);
703      }
704      else {
705         /* fallback to software rendering */
706         _swrast_render_texture(ctx, fb, att);
707         return;
708      }
709   }
710
711   if (!intel_update_wrapper(ctx, irb, image)) {
712       _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
713       _swrast_render_texture(ctx, fb, att);
714       return;
715   }
716
717   DBG("Begin render texture tid %lx tex=%u w=%d h=%d refcount=%d\n",
718       _glthread_GetID(),
719       att->Texture->Name, image->Width, image->Height,
720       irb->Base.RefCount);
721
722   intel_renderbuffer_set_draw_offset(irb, intel_image, att->Zoffset);
723   intel_image->used_as_render_target = true;
724
725#ifndef I915
726   if (need_tile_offset_workaround(brw_context(ctx), irb)) {
727      /* Original gen4 hardware couldn't draw to a non-tile-aligned
728       * destination in a miptree unless you actually setup your
729       * renderbuffer as a miptree and used the fragile
730       * lod/array_index/etc. controls to select the image.  So,
731       * instead, we just make a new single-level miptree and render
732       * into that.
733       */
734      struct intel_context *intel = intel_context(ctx);
735      struct intel_mipmap_tree *new_mt;
736      int width, height, depth;
737
738      intel_miptree_get_dimensions_for_image(image, &width, &height, &depth);
739
740      new_mt = intel_miptree_create(intel, image->TexObject->Target,
741				    intel_image->base.Base.TexFormat,
742				    intel_image->base.Base.Level,
743				    intel_image->base.Base.Level,
744                                    width, height, depth,
745				    true);
746
747      intel_miptree_copy_teximage(intel, intel_image, new_mt);
748      intel_renderbuffer_set_draw_offset(irb, intel_image, att->Zoffset);
749
750      intel_region_reference(&irb->region, intel_image->mt->region);
751      intel_miptree_release(&new_mt);
752   }
753#endif
754   /* update drawing region, etc */
755   intel_draw_buffer(ctx);
756}
757
758
759/**
760 * Called by Mesa when rendering to a texture is done.
761 */
762static void
763intel_finish_render_texture(struct gl_context * ctx,
764                            struct gl_renderbuffer_attachment *att)
765{
766   struct intel_context *intel = intel_context(ctx);
767   struct gl_texture_object *tex_obj = att->Texture;
768   struct gl_texture_image *image =
769      tex_obj->Image[att->CubeMapFace][att->TextureLevel];
770   struct intel_texture_image *intel_image = intel_texture_image(image);
771
772   DBG("Finish render texture tid %lx tex=%u\n",
773       _glthread_GetID(), att->Texture->Name);
774
775   /* Flag that this image may now be validated into the object's miptree. */
776   if (intel_image)
777      intel_image->used_as_render_target = false;
778
779   /* Since we've (probably) rendered to the texture and will (likely) use
780    * it in the texture domain later on in this batchbuffer, flush the
781    * batch.  Once again, we wish for a domain tracker in libdrm to cover
782    * usage inside of a batchbuffer like GEM does in the kernel.
783    */
784   intel_batchbuffer_emit_mi_flush(intel);
785}
786
787/**
788 * Do additional "completeness" testing of a framebuffer object.
789 */
790static void
791intel_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)
792{
793   struct intel_context *intel = intel_context(ctx);
794   const struct intel_renderbuffer *depthRb =
795      intel_get_renderbuffer(fb, BUFFER_DEPTH);
796   const struct intel_renderbuffer *stencilRb =
797      intel_get_renderbuffer(fb, BUFFER_STENCIL);
798   int i;
799
800   /*
801    * The depth and stencil renderbuffers are the same renderbuffer or wrap
802    * the same texture.
803    */
804   if (depthRb && stencilRb) {
805      bool depth_stencil_are_same;
806      if (depthRb == stencilRb)
807	 depth_stencil_are_same = true;
808      else if ((fb->Attachment[BUFFER_DEPTH].Type == GL_TEXTURE) &&
809	       (fb->Attachment[BUFFER_STENCIL].Type == GL_TEXTURE) &&
810	       (fb->Attachment[BUFFER_DEPTH].Texture->Name ==
811		fb->Attachment[BUFFER_STENCIL].Texture->Name))
812	 depth_stencil_are_same = true;
813      else
814	 depth_stencil_are_same = false;
815
816      if (!intel->has_separate_stencil && !depth_stencil_are_same) {
817	 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
818      }
819   }
820
821   for (i = 0; i < Elements(fb->Attachment); i++) {
822      struct gl_renderbuffer *rb;
823      struct intel_renderbuffer *irb;
824
825      if (fb->Attachment[i].Type == GL_NONE)
826	 continue;
827
828      /* A supported attachment will have a Renderbuffer set either
829       * from being a Renderbuffer or being a texture that got the
830       * intel_wrap_texture() treatment.
831       */
832      rb = fb->Attachment[i].Renderbuffer;
833      if (rb == NULL) {
834	 DBG("attachment without renderbuffer\n");
835	 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
836	 continue;
837      }
838
839      irb = intel_renderbuffer(rb);
840      if (irb == NULL) {
841	 DBG("software rendering renderbuffer\n");
842	 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
843	 continue;
844      }
845
846      if (!intel_span_supports_format(irb->Base.Format) ||
847	  !intel->vtbl.render_target_supported(irb->Base.Format)) {
848	 DBG("Unsupported texture/renderbuffer format attached: %s\n",
849	     _mesa_get_format_name(irb->Base.Format));
850	 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
851      }
852   }
853}
854
855/**
856 * Try to do a glBlitFramebuffer using glCopyTexSubImage2D
857 * We can do this when the dst renderbuffer is actually a texture and
858 * there is no scaling, mirroring or scissoring.
859 *
860 * \return new buffer mask indicating the buffers left to blit using the
861 *         normal path.
862 */
863static GLbitfield
864intel_blit_framebuffer_copy_tex_sub_image(struct gl_context *ctx,
865                                          GLint srcX0, GLint srcY0,
866                                          GLint srcX1, GLint srcY1,
867                                          GLint dstX0, GLint dstY0,
868                                          GLint dstX1, GLint dstY1,
869                                          GLbitfield mask, GLenum filter)
870{
871   if (mask & GL_COLOR_BUFFER_BIT) {
872      const struct gl_framebuffer *drawFb = ctx->DrawBuffer;
873      const struct gl_framebuffer *readFb = ctx->ReadBuffer;
874      const struct gl_renderbuffer_attachment *drawAtt =
875         &drawFb->Attachment[drawFb->_ColorDrawBufferIndexes[0]];
876
877      /* If the source and destination are the same size with no
878         mirroring, the rectangles are within the size of the
879         texture and there is no scissor then we can use
880         glCopyTexSubimage2D to implement the blit. This will end
881         up as a fast hardware blit on some drivers */
882      if (drawAtt && drawAtt->Texture &&
883          srcX0 - srcX1 == dstX0 - dstX1 &&
884          srcY0 - srcY1 == dstY0 - dstY1 &&
885          srcX1 >= srcX0 &&
886          srcY1 >= srcY0 &&
887          srcX0 >= 0 && srcX1 <= readFb->Width &&
888          srcY0 >= 0 && srcY1 <= readFb->Height &&
889          dstX0 >= 0 && dstX1 <= drawFb->Width &&
890          dstY0 >= 0 && dstY1 <= drawFb->Height &&
891          !ctx->Scissor.Enabled) {
892         const struct gl_texture_object *texObj = drawAtt->Texture;
893         const GLuint dstLevel = drawAtt->TextureLevel;
894         const GLenum target = texObj->Target;
895
896         struct gl_texture_image *texImage =
897            _mesa_select_tex_image(ctx, texObj, target, dstLevel);
898
899         if (intel_copy_texsubimage(intel_context(ctx),
900                                    intel_texture_image(texImage),
901                                    dstX0, dstY0,
902                                    srcX0, srcY0,
903                                    srcX1 - srcX0, /* width */
904                                    srcY1 - srcY0))
905            mask &= ~GL_COLOR_BUFFER_BIT;
906      }
907   }
908
909   return mask;
910}
911
912static void
913intel_blit_framebuffer(struct gl_context *ctx,
914                       GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
915                       GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
916                       GLbitfield mask, GLenum filter)
917{
918   /* Try faster, glCopyTexSubImage2D approach first which uses the BLT. */
919   mask = intel_blit_framebuffer_copy_tex_sub_image(ctx,
920                                                    srcX0, srcY0, srcX1, srcY1,
921                                                    dstX0, dstY0, dstX1, dstY1,
922                                                    mask, filter);
923   if (mask == 0x0)
924      return;
925
926   _mesa_meta_BlitFramebuffer(ctx,
927                              srcX0, srcY0, srcX1, srcY1,
928                              dstX0, dstY0, dstX1, dstY1,
929                              mask, filter);
930}
931
932/**
933 * Do one-time context initializations related to GL_EXT_framebuffer_object.
934 * Hook in device driver functions.
935 */
936void
937intel_fbo_init(struct intel_context *intel)
938{
939   intel->ctx.Driver.NewFramebuffer = intel_new_framebuffer;
940   intel->ctx.Driver.NewRenderbuffer = intel_new_renderbuffer;
941   intel->ctx.Driver.BindFramebuffer = intel_bind_framebuffer;
942   intel->ctx.Driver.FramebufferRenderbuffer = intel_framebuffer_renderbuffer;
943   intel->ctx.Driver.RenderTexture = intel_render_texture;
944   intel->ctx.Driver.FinishRenderTexture = intel_finish_render_texture;
945   intel->ctx.Driver.ResizeBuffers = intel_resize_buffers;
946   intel->ctx.Driver.ValidateFramebuffer = intel_validate_framebuffer;
947   intel->ctx.Driver.BlitFramebuffer = intel_blit_framebuffer;
948
949#if FEATURE_OES_EGL_image
950   intel->ctx.Driver.EGLImageTargetRenderbufferStorage =
951      intel_image_target_renderbuffer_storage;
952#endif
953}
954