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