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