OSDN Git Service

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