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