intel_fbo.c revision 7eb0aa398b9c0f7d8a224f2a4952f7875067e917
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      return irb->mt->region;
86   else
87      return NULL;
88}
89
90/**
91 * Create a new framebuffer object.
92 */
93static struct gl_framebuffer *
94intel_new_framebuffer(struct gl_context * ctx, GLuint name)
95{
96   /* Only drawable state in intel_framebuffer at this time, just use Mesa's
97    * class
98    */
99   return _mesa_new_framebuffer(ctx, name);
100}
101
102
103/** Called by gl_renderbuffer::Delete() */
104static void
105intel_delete_renderbuffer(struct gl_renderbuffer *rb)
106{
107   struct intel_renderbuffer *irb = intel_renderbuffer(rb);
108
109   ASSERT(irb);
110
111   intel_miptree_release(&irb->mt);
112
113   _mesa_reference_renderbuffer(&irb->wrapped_depth, NULL);
114   _mesa_reference_renderbuffer(&irb->wrapped_stencil, NULL);
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   if (irb->mt->stencil_mt) {
262      bool ok;
263      struct intel_renderbuffer *depth_irb, *stencil_irb;
264
265      /* The RB got allocated as separate stencil.  Hook up our wrapped
266       * renderbuffers so that consumers of intel_get_renderbuffer() end up
267       * with pointers to the separate pieces.
268       */
269      if (!irb->wrapped_depth) {
270	 _mesa_reference_renderbuffer(&irb->wrapped_depth,
271				      intel_new_renderbuffer(ctx, ~0));
272      }
273      if (!irb->wrapped_stencil) {
274	 _mesa_reference_renderbuffer(&irb->wrapped_stencil,
275				      intel_new_renderbuffer(ctx, ~0));
276      }
277
278      depth_irb = intel_renderbuffer(irb->wrapped_depth);
279      stencil_irb = intel_renderbuffer(irb->wrapped_stencil);
280      if (!depth_irb || !stencil_irb) {
281	 intel_miptree_release(&irb->mt);
282	 return false;
283      }
284
285      assert(irb->mt->format == MESA_FORMAT_S8_Z24);
286      ok = intel_renderbuffer_update_wrapper(intel, depth_irb, irb->mt,
287					     0, 0, /* level, layer */
288					     MESA_FORMAT_X8_Z24,
289					     GL_DEPTH_COMPONENT24);
290      assert(ok);
291
292      ok = intel_renderbuffer_update_wrapper(intel, stencil_irb,
293					     irb->mt->stencil_mt,
294					     0, 0, /* level, layer */
295					     MESA_FORMAT_S8,
296					     GL_STENCIL_INDEX);
297      assert(ok);
298   }
299
300   return true;
301}
302
303
304#if FEATURE_OES_EGL_image
305static void
306intel_image_target_renderbuffer_storage(struct gl_context *ctx,
307					struct gl_renderbuffer *rb,
308					void *image_handle)
309{
310   struct intel_context *intel = intel_context(ctx);
311   struct intel_renderbuffer *irb;
312   __DRIscreen *screen;
313   __DRIimage *image;
314
315   screen = intel->intelScreen->driScrnPriv;
316   image = screen->dri2.image->lookupEGLImage(screen, image_handle,
317					      screen->loaderPrivate);
318   if (image == NULL)
319      return;
320
321   /* __DRIimage is opaque to the core so it has to be checked here */
322   switch (image->format) {
323   case MESA_FORMAT_RGBA8888_REV:
324      _mesa_error(&intel->ctx, GL_INVALID_OPERATION,
325            "glEGLImageTargetRenderbufferStorage(unsupported image format");
326      return;
327      break;
328   default:
329      break;
330   }
331
332   irb = intel_renderbuffer(rb);
333   intel_miptree_release(&irb->mt);
334   irb->mt = intel_miptree_create_for_region(intel,
335                                             GL_TEXTURE_2D,
336                                             image->format,
337                                             image->region);
338   if (!irb->mt)
339      return;
340
341   rb->InternalFormat = image->internal_format;
342   rb->Width = image->region->width;
343   rb->Height = image->region->height;
344   rb->Format = image->format;
345   rb->DataType = image->data_type;
346   rb->_BaseFormat = _mesa_base_fbo_format(&intel->ctx,
347					   image->internal_format);
348}
349#endif
350
351/**
352 * Called for each hardware renderbuffer when a _window_ is resized.
353 * Just update fields.
354 * Not used for user-created renderbuffers!
355 */
356static GLboolean
357intel_alloc_window_storage(struct gl_context * ctx, struct gl_renderbuffer *rb,
358                           GLenum internalFormat, GLuint width, GLuint height)
359{
360   ASSERT(rb->Name == 0);
361   rb->Width = width;
362   rb->Height = height;
363   rb->InternalFormat = internalFormat;
364
365   return true;
366}
367
368
369static void
370intel_resize_buffers(struct gl_context *ctx, struct gl_framebuffer *fb,
371		     GLuint width, GLuint height)
372{
373   int i;
374
375   _mesa_resize_framebuffer(ctx, fb, width, height);
376
377   fb->Initialized = true; /* XXX remove someday */
378
379   if (fb->Name != 0) {
380      return;
381   }
382
383
384   /* Make sure all window system renderbuffers are up to date */
385   for (i = BUFFER_FRONT_LEFT; i <= BUFFER_BACK_RIGHT; i++) {
386      struct gl_renderbuffer *rb = fb->Attachment[i].Renderbuffer;
387
388      /* only resize if size is changing */
389      if (rb && (rb->Width != width || rb->Height != height)) {
390	 rb->AllocStorage(ctx, rb, rb->InternalFormat, width, height);
391      }
392   }
393}
394
395
396/** Dummy function for gl_renderbuffer::AllocStorage() */
397static GLboolean
398intel_nop_alloc_storage(struct gl_context * ctx, struct gl_renderbuffer *rb,
399                        GLenum internalFormat, GLuint width, GLuint height)
400{
401   _mesa_problem(ctx, "intel_op_alloc_storage should never be called.");
402   return false;
403}
404
405/**
406 * Create a new intel_renderbuffer which corresponds to an on-screen window,
407 * not a user-created renderbuffer.
408 */
409struct intel_renderbuffer *
410intel_create_renderbuffer(gl_format format)
411{
412   GET_CURRENT_CONTEXT(ctx);
413
414   struct intel_renderbuffer *irb;
415
416   irb = CALLOC_STRUCT(intel_renderbuffer);
417   if (!irb) {
418      _mesa_error(ctx, GL_OUT_OF_MEMORY, "creating renderbuffer");
419      return NULL;
420   }
421
422   _mesa_init_renderbuffer(&irb->Base, 0);
423   irb->Base.ClassID = INTEL_RB_CLASS;
424   irb->Base._BaseFormat = _mesa_get_format_base_format(format);
425   irb->Base.Format = format;
426   irb->Base.InternalFormat = irb->Base._BaseFormat;
427   irb->Base.DataType = intel_mesa_format_to_rb_datatype(format);
428
429   /* intel-specific methods */
430   irb->Base.Delete = intel_delete_renderbuffer;
431   irb->Base.AllocStorage = intel_alloc_window_storage;
432   irb->Base.GetPointer = intel_get_pointer;
433
434   return irb;
435}
436
437/**
438 * Create a new renderbuffer object.
439 * Typically called via glBindRenderbufferEXT().
440 */
441static struct gl_renderbuffer *
442intel_new_renderbuffer(struct gl_context * ctx, GLuint name)
443{
444   /*struct intel_context *intel = intel_context(ctx); */
445   struct intel_renderbuffer *irb;
446
447   irb = CALLOC_STRUCT(intel_renderbuffer);
448   if (!irb) {
449      _mesa_error(ctx, GL_OUT_OF_MEMORY, "creating renderbuffer");
450      return NULL;
451   }
452
453   _mesa_init_renderbuffer(&irb->Base, name);
454   irb->Base.ClassID = INTEL_RB_CLASS;
455
456   /* intel-specific methods */
457   irb->Base.Delete = intel_delete_renderbuffer;
458   irb->Base.AllocStorage = intel_alloc_renderbuffer_storage;
459   irb->Base.GetPointer = intel_get_pointer;
460   /* span routines set in alloc_storage function */
461
462   return &irb->Base;
463}
464
465
466/**
467 * Called via glBindFramebufferEXT().
468 */
469static void
470intel_bind_framebuffer(struct gl_context * ctx, GLenum target,
471                       struct gl_framebuffer *fb, struct gl_framebuffer *fbread)
472{
473   if (target == GL_FRAMEBUFFER_EXT || target == GL_DRAW_FRAMEBUFFER_EXT) {
474      intel_draw_buffer(ctx);
475   }
476   else {
477      /* don't need to do anything if target == GL_READ_FRAMEBUFFER_EXT */
478   }
479}
480
481
482/**
483 * Called via glFramebufferRenderbufferEXT().
484 */
485static void
486intel_framebuffer_renderbuffer(struct gl_context * ctx,
487                               struct gl_framebuffer *fb,
488                               GLenum attachment, struct gl_renderbuffer *rb)
489{
490   DBG("Intel FramebufferRenderbuffer %u %u\n", fb->Name, rb ? rb->Name : 0);
491
492   intel_flush(ctx);
493
494   _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb);
495   intel_draw_buffer(ctx);
496}
497
498static struct intel_renderbuffer*
499intel_renderbuffer_wrap_miptree(struct intel_context *intel,
500                                struct intel_mipmap_tree *mt,
501                                uint32_t level,
502                                uint32_t layer,
503                                gl_format format,
504                                GLenum internal_format);
505
506/**
507 * \par Special case for separate stencil
508 *
509 *     When wrapping a depthstencil texture that uses separate stencil, this
510 *     function is recursively called twice: once to create \c
511 *     irb->wrapped_depth and again to create \c irb->wrapped_stencil.  On the
512 *     call to create \c irb->wrapped_depth, the \c format and \c
513 *     internal_format parameters do not match \c mt->format. In that case, \c
514 *     mt->format is MESA_FORMAT_S8_Z24 and \c format is \c
515 *     MESA_FORMAT_X8_Z24.
516 *
517 * @return true on success
518 */
519static bool
520intel_renderbuffer_update_wrapper(struct intel_context *intel,
521                                  struct intel_renderbuffer *irb,
522                                  struct intel_mipmap_tree *mt,
523                                  uint32_t level,
524                                  uint32_t layer,
525                                  gl_format format,
526                                  GLenum internal_format)
527{
528   struct gl_renderbuffer *rb = &irb->Base;
529
530   rb->Format = format;
531   rb->InternalFormat = internal_format;
532   rb->DataType = intel_mesa_format_to_rb_datatype(rb->Format);
533   rb->_BaseFormat = _mesa_get_format_base_format(rb->Format);
534   rb->Width = mt->level[level].width;
535   rb->Height = mt->level[level].height;
536
537   irb->Base.Delete = intel_delete_renderbuffer;
538   irb->Base.AllocStorage = intel_nop_alloc_storage;
539
540   intel_miptree_check_level_layer(mt, level, layer);
541   irb->mt_level = level;
542   irb->mt_layer = layer;
543
544   if (mt->stencil_mt && _mesa_is_depthstencil_format(rb->InternalFormat)) {
545      assert((irb->wrapped_depth == NULL) == (irb->wrapped_stencil == NULL));
546
547      struct intel_renderbuffer *depth_irb;
548      struct intel_renderbuffer *stencil_irb;
549
550      if (!irb->wrapped_depth) {
551	 depth_irb = intel_renderbuffer_wrap_miptree(intel,
552	                                             mt, level, layer,
553	                                             MESA_FORMAT_X8_Z24,
554	                                             GL_DEPTH_COMPONENT24);
555	 stencil_irb = intel_renderbuffer_wrap_miptree(intel,
556	                                               mt->stencil_mt,
557	                                               level, layer,
558	                                               MESA_FORMAT_S8,
559	                                               GL_STENCIL_INDEX8);
560	 _mesa_reference_renderbuffer(&irb->wrapped_depth, &depth_irb->Base);
561	 _mesa_reference_renderbuffer(&irb->wrapped_stencil, &stencil_irb->Base);
562
563	 if (!irb->wrapped_depth || !irb->wrapped_stencil)
564	    return false;
565      } else {
566	 bool ok = true;
567
568	 depth_irb = intel_renderbuffer(irb->wrapped_depth);
569	 stencil_irb = intel_renderbuffer(irb->wrapped_stencil);
570
571	 ok &= intel_renderbuffer_update_wrapper(intel,
572	                                         depth_irb,
573	                                         mt,
574	                                         level, layer,
575	                                         MESA_FORMAT_X8_Z24,
576	                                         GL_DEPTH_COMPONENT24);
577	 ok &= intel_renderbuffer_update_wrapper(intel,
578	                                         stencil_irb,
579	                                         mt->stencil_mt,
580	                                         level, layer,
581	                                         MESA_FORMAT_S8,
582	                                         GL_STENCIL_INDEX8);
583	 if (!ok)
584	    return false;
585      }
586
587      intel_miptree_reference(&depth_irb->mt->stencil_mt, stencil_irb->mt);
588      intel_miptree_reference(&irb->mt, depth_irb->mt);
589   } else {
590      intel_miptree_reference(&irb->mt, mt);
591      intel_renderbuffer_set_draw_offset(irb);
592
593      if (mt->hiz_mt == NULL &&
594	  intel->vtbl.is_hiz_depth_format(intel, rb->Format)) {
595	 intel_miptree_alloc_hiz(intel, mt);
596         if (!mt->hiz_mt)
597            return false;
598      }
599   }
600
601   return true;
602}
603
604/**
605 * \brief Wrap a renderbuffer around a single slice of a miptree.
606 *
607 * Called by glFramebufferTexture*(). This just allocates a
608 * ``struct intel_renderbuffer`` then calls
609 * intel_renderbuffer_update_wrapper() to do the real work.
610 *
611 * \see intel_renderbuffer_update_wrapper()
612 */
613static struct intel_renderbuffer*
614intel_renderbuffer_wrap_miptree(struct intel_context *intel,
615                                struct intel_mipmap_tree *mt,
616                                uint32_t level,
617                                uint32_t layer,
618                                gl_format format,
619                                GLenum internal_format)
620
621{
622   struct gl_context *ctx = &intel->ctx;
623   struct gl_renderbuffer *rb;
624   struct intel_renderbuffer *irb;
625
626   intel_miptree_check_level_layer(mt, level, layer);
627
628   rb = intel_new_renderbuffer(ctx, ~0);
629   irb = intel_renderbuffer(rb);
630   if (!irb)
631      return NULL;
632
633   if (!intel_renderbuffer_update_wrapper(intel, irb,
634                                          mt, level, layer,
635                                          format, internal_format)) {
636      free(irb);
637      return NULL;
638   }
639
640   return irb;
641}
642
643void
644intel_renderbuffer_set_draw_offset(struct intel_renderbuffer *irb)
645{
646   unsigned int dst_x, dst_y;
647
648   /* compute offset of the particular 2D image within the texture region */
649   intel_miptree_get_image_offset(irb->mt,
650				  irb->mt_level,
651				  0, /* face, which we ignore */
652				  irb->mt_layer,
653				  &dst_x, &dst_y);
654
655   irb->draw_x = dst_x;
656   irb->draw_y = dst_y;
657}
658
659/**
660 * Rendering to tiled buffers requires that the base address of the
661 * buffer be aligned to a page boundary.  We generally render to
662 * textures by pointing the surface at the mipmap image level, which
663 * may not be aligned to a tile boundary.
664 *
665 * This function returns an appropriately-aligned base offset
666 * according to the tiling restrictions, plus any required x/y offset
667 * from there.
668 */
669uint32_t
670intel_renderbuffer_tile_offsets(struct intel_renderbuffer *irb,
671				uint32_t *tile_x,
672				uint32_t *tile_y)
673{
674   struct intel_region *region = irb->mt->region;
675   int cpp = region->cpp;
676   uint32_t pitch = region->pitch * cpp;
677
678   if (region->tiling == I915_TILING_NONE) {
679      *tile_x = 0;
680      *tile_y = 0;
681      return irb->draw_x * cpp + irb->draw_y * pitch;
682   } else if (region->tiling == I915_TILING_X) {
683      *tile_x = irb->draw_x % (512 / cpp);
684      *tile_y = irb->draw_y % 8;
685      return ((irb->draw_y / 8) * (8 * pitch) +
686	      (irb->draw_x - *tile_x) / (512 / cpp) * 4096);
687   } else {
688      assert(region->tiling == I915_TILING_Y);
689      *tile_x = irb->draw_x % (128 / cpp);
690      *tile_y = irb->draw_y % 32;
691      return ((irb->draw_y / 32) * (32 * pitch) +
692	      (irb->draw_x - *tile_x) / (128 / cpp) * 4096);
693   }
694}
695
696#ifndef I915
697static bool
698need_tile_offset_workaround(struct brw_context *brw,
699			    struct intel_renderbuffer *irb)
700{
701   uint32_t tile_x, tile_y;
702
703   if (brw->has_surface_tile_offset)
704      return false;
705
706   intel_renderbuffer_tile_offsets(irb, &tile_x, &tile_y);
707
708   return tile_x != 0 || tile_y != 0;
709}
710#endif
711
712/**
713 * Called by glFramebufferTexture[123]DEXT() (and other places) to
714 * prepare for rendering into texture memory.  This might be called
715 * many times to choose different texture levels, cube faces, etc
716 * before intel_finish_render_texture() is ever called.
717 */
718static void
719intel_render_texture(struct gl_context * ctx,
720                     struct gl_framebuffer *fb,
721                     struct gl_renderbuffer_attachment *att)
722{
723   struct intel_context *intel = intel_context(ctx);
724   struct gl_texture_image *image = _mesa_get_attachment_teximage(att);
725   struct intel_renderbuffer *irb = intel_renderbuffer(att->Renderbuffer);
726   struct intel_texture_image *intel_image = intel_texture_image(image);
727   struct intel_mipmap_tree *mt = intel_image->mt;
728
729   (void) fb;
730
731   int layer;
732   if (att->CubeMapFace > 0) {
733      assert(att->Zoffset == 0);
734      layer = att->CubeMapFace;
735   } else {
736      layer = att->Zoffset;
737   }
738
739   if (!intel_image->mt) {
740      /* Fallback on drawing to a texture that doesn't have a miptree
741       * (has a border, width/height 0, etc.)
742       */
743      _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
744      _swrast_render_texture(ctx, fb, att);
745      return;
746   }
747   else if (!irb) {
748      irb = intel_renderbuffer_wrap_miptree(intel,
749                                            mt,
750                                            att->TextureLevel,
751                                            layer,
752                                            image->TexFormat,
753                                            image->InternalFormat);
754
755      if (irb) {
756         /* bind the wrapper to the attachment point */
757         _mesa_reference_renderbuffer(&att->Renderbuffer, &irb->Base);
758      }
759      else {
760         /* fallback to software rendering */
761         _swrast_render_texture(ctx, fb, att);
762         return;
763      }
764   }
765
766   if (!intel_renderbuffer_update_wrapper(intel, irb,
767                                          mt, att->TextureLevel, layer,
768                                          image->TexFormat,
769                                          image->InternalFormat)) {
770       _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
771       _swrast_render_texture(ctx, fb, att);
772       return;
773   }
774
775   DBG("Begin render %s texture tex=%u w=%d h=%d refcount=%d\n",
776       _mesa_get_format_name(image->TexFormat),
777       att->Texture->Name, image->Width, image->Height,
778       irb->Base.RefCount);
779
780   intel_image->used_as_render_target = true;
781
782#ifndef I915
783   if (need_tile_offset_workaround(brw_context(ctx), irb)) {
784      /* Original gen4 hardware couldn't draw to a non-tile-aligned
785       * destination in a miptree unless you actually setup your
786       * renderbuffer as a miptree and used the fragile
787       * lod/array_index/etc. controls to select the image.  So,
788       * instead, we just make a new single-level miptree and render
789       * into that.
790       */
791      struct intel_context *intel = intel_context(ctx);
792      struct intel_mipmap_tree *new_mt;
793      int width, height, depth;
794
795      intel_miptree_get_dimensions_for_image(image, &width, &height, &depth);
796
797      new_mt = intel_miptree_create(intel, image->TexObject->Target,
798				    intel_image->base.Base.TexFormat,
799				    intel_image->base.Base.Level,
800				    intel_image->base.Base.Level,
801                                    width, height, depth,
802				    true);
803
804      intel_miptree_copy_teximage(intel, intel_image, new_mt);
805      intel_renderbuffer_set_draw_offset(irb);
806
807      intel_miptree_reference(&irb->mt, intel_image->mt);
808      intel_miptree_release(&new_mt);
809   }
810#endif
811   /* update drawing region, etc */
812   intel_draw_buffer(ctx);
813}
814
815
816/**
817 * Called by Mesa when rendering to a texture is done.
818 */
819static void
820intel_finish_render_texture(struct gl_context * ctx,
821                            struct gl_renderbuffer_attachment *att)
822{
823   struct intel_context *intel = intel_context(ctx);
824   struct gl_texture_object *tex_obj = att->Texture;
825   struct gl_texture_image *image =
826      tex_obj->Image[att->CubeMapFace][att->TextureLevel];
827   struct intel_texture_image *intel_image = intel_texture_image(image);
828
829   DBG("Finish render %s texture tex=%u\n",
830       _mesa_get_format_name(image->TexFormat), att->Texture->Name);
831
832   /* Flag that this image may now be validated into the object's miptree. */
833   if (intel_image)
834      intel_image->used_as_render_target = false;
835
836   /* Since we've (probably) rendered to the texture and will (likely) use
837    * it in the texture domain later on in this batchbuffer, flush the
838    * batch.  Once again, we wish for a domain tracker in libdrm to cover
839    * usage inside of a batchbuffer like GEM does in the kernel.
840    */
841   intel_batchbuffer_emit_mi_flush(intel);
842}
843
844/**
845 * Do additional "completeness" testing of a framebuffer object.
846 */
847static void
848intel_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)
849{
850   struct intel_context *intel = intel_context(ctx);
851   const struct intel_renderbuffer *depthRb =
852      intel_get_renderbuffer(fb, BUFFER_DEPTH);
853   const struct intel_renderbuffer *stencilRb =
854      intel_get_renderbuffer(fb, BUFFER_STENCIL);
855   struct intel_mipmap_tree *depth_mt = NULL, *stencil_mt = NULL;
856   int i;
857
858   if (depthRb)
859      depth_mt = depthRb->mt;
860   if (stencilRb)
861      stencil_mt = stencilRb->mt;
862
863   if (depth_mt && stencil_mt) {
864      if (depth_mt == stencil_mt) {
865	 /* For true packed depth/stencil (not faked on prefers-separate-stencil
866	  * hardware) we need to be sure they're the same level/layer, since
867	  * we'll be emitting a single packet describing the packed setup.
868	  */
869	 if (depthRb->mt_level != stencilRb->mt_level ||
870	     depthRb->mt_layer != stencilRb->mt_layer) {
871	    fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
872	 }
873      } else {
874	 if (!intel->has_separate_stencil)
875	    fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
876	 if (stencil_mt->format != MESA_FORMAT_S8)
877	    fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
878      }
879   }
880
881   for (i = 0; i < Elements(fb->Attachment); i++) {
882      struct gl_renderbuffer *rb;
883      struct intel_renderbuffer *irb;
884
885      if (fb->Attachment[i].Type == GL_NONE)
886	 continue;
887
888      /* A supported attachment will have a Renderbuffer set either
889       * from being a Renderbuffer or being a texture that got the
890       * intel_wrap_texture() treatment.
891       */
892      rb = fb->Attachment[i].Renderbuffer;
893      if (rb == NULL) {
894	 DBG("attachment without renderbuffer\n");
895	 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
896	 continue;
897      }
898
899      irb = intel_renderbuffer(rb);
900      if (irb == NULL) {
901	 DBG("software rendering renderbuffer\n");
902	 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
903	 continue;
904      }
905
906      if (!intel->vtbl.render_target_supported(intel, irb->Base.Format)) {
907	 DBG("Unsupported HW texture/renderbuffer format attached: %s\n",
908	     _mesa_get_format_name(irb->Base.Format));
909	 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
910      }
911
912#ifdef I915
913      if (!intel_span_supports_format(irb->Base.Format)) {
914	 DBG("Unsupported swrast texture/renderbuffer format attached: %s\n",
915	     _mesa_get_format_name(irb->Base.Format));
916	 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
917      }
918#endif
919   }
920}
921
922/**
923 * Try to do a glBlitFramebuffer using glCopyTexSubImage2D
924 * We can do this when the dst renderbuffer is actually a texture and
925 * there is no scaling, mirroring or scissoring.
926 *
927 * \return new buffer mask indicating the buffers left to blit using the
928 *         normal path.
929 */
930static GLbitfield
931intel_blit_framebuffer_copy_tex_sub_image(struct gl_context *ctx,
932                                          GLint srcX0, GLint srcY0,
933                                          GLint srcX1, GLint srcY1,
934                                          GLint dstX0, GLint dstY0,
935                                          GLint dstX1, GLint dstY1,
936                                          GLbitfield mask, GLenum filter)
937{
938   if (mask & GL_COLOR_BUFFER_BIT) {
939      const struct gl_framebuffer *drawFb = ctx->DrawBuffer;
940      const struct gl_framebuffer *readFb = ctx->ReadBuffer;
941      const struct gl_renderbuffer_attachment *drawAtt =
942         &drawFb->Attachment[drawFb->_ColorDrawBufferIndexes[0]];
943
944      /* If the source and destination are the same size with no
945         mirroring, the rectangles are within the size of the
946         texture and there is no scissor then we can use
947         glCopyTexSubimage2D to implement the blit. This will end
948         up as a fast hardware blit on some drivers */
949      if (drawAtt && drawAtt->Texture &&
950          srcX0 - srcX1 == dstX0 - dstX1 &&
951          srcY0 - srcY1 == dstY0 - dstY1 &&
952          srcX1 >= srcX0 &&
953          srcY1 >= srcY0 &&
954          srcX0 >= 0 && srcX1 <= readFb->Width &&
955          srcY0 >= 0 && srcY1 <= readFb->Height &&
956          dstX0 >= 0 && dstX1 <= drawFb->Width &&
957          dstY0 >= 0 && dstY1 <= drawFb->Height &&
958          !ctx->Scissor.Enabled) {
959         const struct gl_texture_object *texObj = drawAtt->Texture;
960         const GLuint dstLevel = drawAtt->TextureLevel;
961         const GLenum target = texObj->Target;
962
963         struct gl_texture_image *texImage =
964            _mesa_select_tex_image(ctx, texObj, target, dstLevel);
965
966         if (intel_copy_texsubimage(intel_context(ctx),
967                                    intel_texture_image(texImage),
968                                    dstX0, dstY0,
969                                    srcX0, srcY0,
970                                    srcX1 - srcX0, /* width */
971                                    srcY1 - srcY0))
972            mask &= ~GL_COLOR_BUFFER_BIT;
973      }
974   }
975
976   return mask;
977}
978
979static void
980intel_blit_framebuffer(struct gl_context *ctx,
981                       GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
982                       GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
983                       GLbitfield mask, GLenum filter)
984{
985   /* Try faster, glCopyTexSubImage2D approach first which uses the BLT. */
986   mask = intel_blit_framebuffer_copy_tex_sub_image(ctx,
987                                                    srcX0, srcY0, srcX1, srcY1,
988                                                    dstX0, dstY0, dstX1, dstY1,
989                                                    mask, filter);
990   if (mask == 0x0)
991      return;
992
993   _mesa_meta_BlitFramebuffer(ctx,
994                              srcX0, srcY0, srcX1, srcY1,
995                              dstX0, dstY0, dstX1, dstY1,
996                              mask, filter);
997}
998
999void
1000intel_renderbuffer_set_needs_hiz_resolve(struct intel_renderbuffer *irb)
1001{
1002   if (irb->mt) {
1003      intel_miptree_slice_set_needs_hiz_resolve(irb->mt,
1004                                                irb->mt_level,
1005                                                irb->mt_layer);
1006   } else if (irb->wrapped_depth) {
1007      intel_renderbuffer_set_needs_hiz_resolve(
1008	    intel_renderbuffer(irb->wrapped_depth));
1009   } else {
1010      return;
1011   }
1012}
1013
1014void
1015intel_renderbuffer_set_needs_depth_resolve(struct intel_renderbuffer *irb)
1016{
1017   if (irb->mt) {
1018      intel_miptree_slice_set_needs_depth_resolve(irb->mt,
1019                                                  irb->mt_level,
1020                                                  irb->mt_layer);
1021   } else if (irb->wrapped_depth) {
1022      intel_renderbuffer_set_needs_depth_resolve(
1023	    intel_renderbuffer(irb->wrapped_depth));
1024   } else {
1025      return;
1026   }
1027}
1028
1029bool
1030intel_renderbuffer_resolve_hiz(struct intel_context *intel,
1031			       struct intel_renderbuffer *irb)
1032{
1033   if (irb->mt)
1034      return intel_miptree_slice_resolve_hiz(intel,
1035                                             irb->mt,
1036                                             irb->mt_level,
1037                                             irb->mt_layer);
1038   if (irb->wrapped_depth)
1039      return intel_renderbuffer_resolve_hiz(intel,
1040					    intel_renderbuffer(irb->wrapped_depth));
1041
1042   return false;
1043}
1044
1045bool
1046intel_renderbuffer_resolve_depth(struct intel_context *intel,
1047				 struct intel_renderbuffer *irb)
1048{
1049   if (irb->mt)
1050      return intel_miptree_slice_resolve_depth(intel,
1051                                               irb->mt,
1052                                               irb->mt_level,
1053                                               irb->mt_layer);
1054
1055   if (irb->wrapped_depth)
1056      return intel_renderbuffer_resolve_depth(intel,
1057                                              intel_renderbuffer(irb->wrapped_depth));
1058
1059   return false;
1060}
1061
1062/**
1063 * Do one-time context initializations related to GL_EXT_framebuffer_object.
1064 * Hook in device driver functions.
1065 */
1066void
1067intel_fbo_init(struct intel_context *intel)
1068{
1069   intel->ctx.Driver.NewFramebuffer = intel_new_framebuffer;
1070   intel->ctx.Driver.NewRenderbuffer = intel_new_renderbuffer;
1071   intel->ctx.Driver.MapRenderbuffer = intel_map_renderbuffer;
1072   intel->ctx.Driver.UnmapRenderbuffer = intel_unmap_renderbuffer;
1073   intel->ctx.Driver.BindFramebuffer = intel_bind_framebuffer;
1074   intel->ctx.Driver.FramebufferRenderbuffer = intel_framebuffer_renderbuffer;
1075   intel->ctx.Driver.RenderTexture = intel_render_texture;
1076   intel->ctx.Driver.FinishRenderTexture = intel_finish_render_texture;
1077   intel->ctx.Driver.ResizeBuffers = intel_resize_buffers;
1078   intel->ctx.Driver.ValidateFramebuffer = intel_validate_framebuffer;
1079   intel->ctx.Driver.BlitFramebuffer = intel_blit_framebuffer;
1080
1081#if FEATURE_OES_EGL_image
1082   intel->ctx.Driver.EGLImageTargetRenderbufferStorage =
1083      intel_image_target_renderbuffer_storage;
1084#endif
1085}
1086