63a3d302727f55b1e66076021c3e67582e67e45a
[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 "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
59 static struct gl_renderbuffer *
60 intel_new_renderbuffer(struct gl_context * ctx, GLuint name);
61
62 static bool
63 intel_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
71 bool
72 intel_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
80 struct intel_region*
81 intel_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 */
93 static struct gl_framebuffer *
94 intel_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() */
104 static void
105 intel_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 */
122 static void
123 intel_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 */
169 static void
170 intel_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 */
185 static void *
186 intel_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 */
200 GLboolean
201 intel_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
305 static void
306 intel_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 */
356 static GLboolean
357 intel_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
369 static void
370 intel_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() */
397 static GLboolean
398 intel_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 */
409 struct intel_renderbuffer *
410 intel_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 */
441 static struct gl_renderbuffer *
442 intel_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 */
469 static void
470 intel_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 */
485 static void
486 intel_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
498 static struct intel_renderbuffer*
499 intel_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 */
519 static bool
520 intel_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 */
613 static struct intel_renderbuffer*
614 intel_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 const GLuint name = ~0; /* not significant, but distinct for debugging */
623 struct gl_context *ctx = &intel->ctx;
624 struct intel_renderbuffer *irb;
625
626 intel_miptree_check_level_layer(mt, level, layer);
627
628 irb = CALLOC_STRUCT(intel_renderbuffer);
629 if (!irb) {
630 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glFramebufferTexture");
631 return NULL;
632 }
633
634 _mesa_init_renderbuffer(&irb->Base, name);
635 irb->Base.ClassID = INTEL_RB_CLASS;
636
637 if (!intel_renderbuffer_update_wrapper(intel, irb,
638 mt, level, layer,
639 format, internal_format)) {
640 free(irb);
641 return NULL;
642 }
643
644 return irb;
645 }
646
647 void
648 intel_renderbuffer_set_draw_offset(struct intel_renderbuffer *irb)
649 {
650 unsigned int dst_x, dst_y;
651
652 /* compute offset of the particular 2D image within the texture region */
653 intel_miptree_get_image_offset(irb->mt,
654 irb->mt_level,
655 0, /* face, which we ignore */
656 irb->mt_layer,
657 &dst_x, &dst_y);
658
659 irb->draw_x = dst_x;
660 irb->draw_y = dst_y;
661 }
662
663 /**
664 * Rendering to tiled buffers requires that the base address of the
665 * buffer be aligned to a page boundary. We generally render to
666 * textures by pointing the surface at the mipmap image level, which
667 * may not be aligned to a tile boundary.
668 *
669 * This function returns an appropriately-aligned base offset
670 * according to the tiling restrictions, plus any required x/y offset
671 * from there.
672 */
673 uint32_t
674 intel_renderbuffer_tile_offsets(struct intel_renderbuffer *irb,
675 uint32_t *tile_x,
676 uint32_t *tile_y)
677 {
678 struct intel_region *region = irb->mt->region;
679 int cpp = region->cpp;
680 uint32_t pitch = region->pitch * cpp;
681
682 if (region->tiling == I915_TILING_NONE) {
683 *tile_x = 0;
684 *tile_y = 0;
685 return irb->draw_x * cpp + irb->draw_y * pitch;
686 } else if (region->tiling == I915_TILING_X) {
687 *tile_x = irb->draw_x % (512 / cpp);
688 *tile_y = irb->draw_y % 8;
689 return ((irb->draw_y / 8) * (8 * pitch) +
690 (irb->draw_x - *tile_x) / (512 / cpp) * 4096);
691 } else {
692 assert(region->tiling == I915_TILING_Y);
693 *tile_x = irb->draw_x % (128 / cpp);
694 *tile_y = irb->draw_y % 32;
695 return ((irb->draw_y / 32) * (32 * pitch) +
696 (irb->draw_x - *tile_x) / (128 / cpp) * 4096);
697 }
698 }
699
700 #ifndef I915
701 static bool
702 need_tile_offset_workaround(struct brw_context *brw,
703 struct intel_renderbuffer *irb)
704 {
705 uint32_t tile_x, tile_y;
706
707 if (brw->has_surface_tile_offset)
708 return false;
709
710 intel_renderbuffer_tile_offsets(irb, &tile_x, &tile_y);
711
712 return tile_x != 0 || tile_y != 0;
713 }
714 #endif
715
716 /**
717 * Called by glFramebufferTexture[123]DEXT() (and other places) to
718 * prepare for rendering into texture memory. This might be called
719 * many times to choose different texture levels, cube faces, etc
720 * before intel_finish_render_texture() is ever called.
721 */
722 static void
723 intel_render_texture(struct gl_context * ctx,
724 struct gl_framebuffer *fb,
725 struct gl_renderbuffer_attachment *att)
726 {
727 struct intel_context *intel = intel_context(ctx);
728 struct gl_texture_image *image = _mesa_get_attachment_teximage(att);
729 struct intel_renderbuffer *irb = intel_renderbuffer(att->Renderbuffer);
730 struct intel_texture_image *intel_image = intel_texture_image(image);
731 struct intel_mipmap_tree *mt = intel_image->mt;
732
733 (void) fb;
734
735 int layer;
736 if (att->CubeMapFace > 0) {
737 assert(att->Zoffset == 0);
738 layer = att->CubeMapFace;
739 } else {
740 layer = att->Zoffset;
741 }
742
743 if (!intel_image->mt) {
744 /* Fallback on drawing to a texture that doesn't have a miptree
745 * (has a border, width/height 0, etc.)
746 */
747 _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
748 _swrast_render_texture(ctx, fb, att);
749 return;
750 }
751 else if (!irb) {
752 irb = intel_renderbuffer_wrap_miptree(intel,
753 mt,
754 att->TextureLevel,
755 layer,
756 image->TexFormat,
757 image->InternalFormat);
758
759 if (irb) {
760 /* bind the wrapper to the attachment point */
761 _mesa_reference_renderbuffer(&att->Renderbuffer, &irb->Base);
762 }
763 else {
764 /* fallback to software rendering */
765 _swrast_render_texture(ctx, fb, att);
766 return;
767 }
768 }
769
770 if (!intel_renderbuffer_update_wrapper(intel, irb,
771 mt, att->TextureLevel, layer,
772 image->TexFormat,
773 image->InternalFormat)) {
774 _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
775 _swrast_render_texture(ctx, fb, att);
776 return;
777 }
778
779 DBG("Begin render %s texture tex=%u w=%d h=%d refcount=%d\n",
780 _mesa_get_format_name(image->TexFormat),
781 att->Texture->Name, image->Width, image->Height,
782 irb->Base.RefCount);
783
784 intel_image->used_as_render_target = true;
785
786 #ifndef I915
787 if (need_tile_offset_workaround(brw_context(ctx), irb)) {
788 /* Original gen4 hardware couldn't draw to a non-tile-aligned
789 * destination in a miptree unless you actually setup your
790 * renderbuffer as a miptree and used the fragile
791 * lod/array_index/etc. controls to select the image. So,
792 * instead, we just make a new single-level miptree and render
793 * into that.
794 */
795 struct intel_context *intel = intel_context(ctx);
796 struct intel_mipmap_tree *new_mt;
797 int width, height, depth;
798
799 intel_miptree_get_dimensions_for_image(image, &width, &height, &depth);
800
801 new_mt = intel_miptree_create(intel, image->TexObject->Target,
802 intel_image->base.Base.TexFormat,
803 intel_image->base.Base.Level,
804 intel_image->base.Base.Level,
805 width, height, depth,
806 true);
807
808 intel_miptree_copy_teximage(intel, intel_image, new_mt);
809 intel_renderbuffer_set_draw_offset(irb);
810
811 intel_miptree_reference(&irb->mt, intel_image->mt);
812 intel_miptree_release(&new_mt);
813 }
814 #endif
815 /* update drawing region, etc */
816 intel_draw_buffer(ctx);
817 }
818
819
820 /**
821 * Called by Mesa when rendering to a texture is done.
822 */
823 static void
824 intel_finish_render_texture(struct gl_context * ctx,
825 struct gl_renderbuffer_attachment *att)
826 {
827 struct intel_context *intel = intel_context(ctx);
828 struct gl_texture_object *tex_obj = att->Texture;
829 struct gl_texture_image *image =
830 tex_obj->Image[att->CubeMapFace][att->TextureLevel];
831 struct intel_texture_image *intel_image = intel_texture_image(image);
832
833 DBG("Finish render %s texture tex=%u\n",
834 _mesa_get_format_name(image->TexFormat), att->Texture->Name);
835
836 /* Flag that this image may now be validated into the object's miptree. */
837 if (intel_image)
838 intel_image->used_as_render_target = false;
839
840 /* Since we've (probably) rendered to the texture and will (likely) use
841 * it in the texture domain later on in this batchbuffer, flush the
842 * batch. Once again, we wish for a domain tracker in libdrm to cover
843 * usage inside of a batchbuffer like GEM does in the kernel.
844 */
845 intel_batchbuffer_emit_mi_flush(intel);
846 }
847
848 /**
849 * Do additional "completeness" testing of a framebuffer object.
850 */
851 static void
852 intel_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)
853 {
854 struct intel_context *intel = intel_context(ctx);
855 const struct intel_renderbuffer *depthRb =
856 intel_get_renderbuffer(fb, BUFFER_DEPTH);
857 const struct intel_renderbuffer *stencilRb =
858 intel_get_renderbuffer(fb, BUFFER_STENCIL);
859 int i;
860
861 /*
862 * The depth and stencil renderbuffers are the same renderbuffer or wrap
863 * the same texture.
864 */
865 if (depthRb && stencilRb) {
866 bool depth_stencil_are_same;
867 if (depthRb == stencilRb)
868 depth_stencil_are_same = true;
869 else if ((fb->Attachment[BUFFER_DEPTH].Type == GL_TEXTURE) &&
870 (fb->Attachment[BUFFER_STENCIL].Type == GL_TEXTURE) &&
871 (fb->Attachment[BUFFER_DEPTH].Texture->Name ==
872 fb->Attachment[BUFFER_STENCIL].Texture->Name))
873 depth_stencil_are_same = true;
874 else
875 depth_stencil_are_same = false;
876
877 if (!intel->has_separate_stencil && !depth_stencil_are_same) {
878 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
879 }
880 }
881
882 for (i = 0; i < Elements(fb->Attachment); i++) {
883 struct gl_renderbuffer *rb;
884 struct intel_renderbuffer *irb;
885
886 if (fb->Attachment[i].Type == GL_NONE)
887 continue;
888
889 /* A supported attachment will have a Renderbuffer set either
890 * from being a Renderbuffer or being a texture that got the
891 * intel_wrap_texture() treatment.
892 */
893 rb = fb->Attachment[i].Renderbuffer;
894 if (rb == NULL) {
895 DBG("attachment without renderbuffer\n");
896 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
897 continue;
898 }
899
900 irb = intel_renderbuffer(rb);
901 if (irb == NULL) {
902 DBG("software rendering renderbuffer\n");
903 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
904 continue;
905 }
906
907 if (!intel->vtbl.render_target_supported(intel, irb->Base.Format)) {
908 DBG("Unsupported HW texture/renderbuffer format attached: %s\n",
909 _mesa_get_format_name(irb->Base.Format));
910 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
911 }
912
913 #ifdef I915
914 if (!intel_span_supports_format(irb->Base.Format)) {
915 DBG("Unsupported swrast texture/renderbuffer format attached: %s\n",
916 _mesa_get_format_name(irb->Base.Format));
917 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
918 }
919 #endif
920 }
921 }
922
923 /**
924 * Try to do a glBlitFramebuffer using glCopyTexSubImage2D
925 * We can do this when the dst renderbuffer is actually a texture and
926 * there is no scaling, mirroring or scissoring.
927 *
928 * \return new buffer mask indicating the buffers left to blit using the
929 * normal path.
930 */
931 static GLbitfield
932 intel_blit_framebuffer_copy_tex_sub_image(struct gl_context *ctx,
933 GLint srcX0, GLint srcY0,
934 GLint srcX1, GLint srcY1,
935 GLint dstX0, GLint dstY0,
936 GLint dstX1, GLint dstY1,
937 GLbitfield mask, GLenum filter)
938 {
939 if (mask & GL_COLOR_BUFFER_BIT) {
940 const struct gl_framebuffer *drawFb = ctx->DrawBuffer;
941 const struct gl_framebuffer *readFb = ctx->ReadBuffer;
942 const struct gl_renderbuffer_attachment *drawAtt =
943 &drawFb->Attachment[drawFb->_ColorDrawBufferIndexes[0]];
944
945 /* If the source and destination are the same size with no
946 mirroring, the rectangles are within the size of the
947 texture and there is no scissor then we can use
948 glCopyTexSubimage2D to implement the blit. This will end
949 up as a fast hardware blit on some drivers */
950 if (drawAtt && drawAtt->Texture &&
951 srcX0 - srcX1 == dstX0 - dstX1 &&
952 srcY0 - srcY1 == dstY0 - dstY1 &&
953 srcX1 >= srcX0 &&
954 srcY1 >= srcY0 &&
955 srcX0 >= 0 && srcX1 <= readFb->Width &&
956 srcY0 >= 0 && srcY1 <= readFb->Height &&
957 dstX0 >= 0 && dstX1 <= drawFb->Width &&
958 dstY0 >= 0 && dstY1 <= drawFb->Height &&
959 !ctx->Scissor.Enabled) {
960 const struct gl_texture_object *texObj = drawAtt->Texture;
961 const GLuint dstLevel = drawAtt->TextureLevel;
962 const GLenum target = texObj->Target;
963
964 struct gl_texture_image *texImage =
965 _mesa_select_tex_image(ctx, texObj, target, dstLevel);
966
967 if (intel_copy_texsubimage(intel_context(ctx),
968 intel_texture_image(texImage),
969 dstX0, dstY0,
970 srcX0, srcY0,
971 srcX1 - srcX0, /* width */
972 srcY1 - srcY0))
973 mask &= ~GL_COLOR_BUFFER_BIT;
974 }
975 }
976
977 return mask;
978 }
979
980 static void
981 intel_blit_framebuffer(struct gl_context *ctx,
982 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
983 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
984 GLbitfield mask, GLenum filter)
985 {
986 /* Try faster, glCopyTexSubImage2D approach first which uses the BLT. */
987 mask = intel_blit_framebuffer_copy_tex_sub_image(ctx,
988 srcX0, srcY0, srcX1, srcY1,
989 dstX0, dstY0, dstX1, dstY1,
990 mask, filter);
991 if (mask == 0x0)
992 return;
993
994 _mesa_meta_BlitFramebuffer(ctx,
995 srcX0, srcY0, srcX1, srcY1,
996 dstX0, dstY0, dstX1, dstY1,
997 mask, filter);
998 }
999
1000 void
1001 intel_renderbuffer_set_needs_hiz_resolve(struct intel_renderbuffer *irb)
1002 {
1003 if (irb->mt) {
1004 intel_miptree_slice_set_needs_hiz_resolve(irb->mt,
1005 irb->mt_level,
1006 irb->mt_layer);
1007 } else if (irb->wrapped_depth) {
1008 intel_renderbuffer_set_needs_hiz_resolve(
1009 intel_renderbuffer(irb->wrapped_depth));
1010 } else {
1011 return;
1012 }
1013 }
1014
1015 void
1016 intel_renderbuffer_set_needs_depth_resolve(struct intel_renderbuffer *irb)
1017 {
1018 if (irb->mt) {
1019 intel_miptree_slice_set_needs_depth_resolve(irb->mt,
1020 irb->mt_level,
1021 irb->mt_layer);
1022 } else if (irb->wrapped_depth) {
1023 intel_renderbuffer_set_needs_depth_resolve(
1024 intel_renderbuffer(irb->wrapped_depth));
1025 } else {
1026 return;
1027 }
1028 }
1029
1030 bool
1031 intel_renderbuffer_resolve_hiz(struct intel_context *intel,
1032 struct intel_renderbuffer *irb)
1033 {
1034 if (irb->mt)
1035 return intel_miptree_slice_resolve_hiz(intel,
1036 irb->mt,
1037 irb->mt_level,
1038 irb->mt_layer);
1039 if (irb->wrapped_depth)
1040 return intel_renderbuffer_resolve_hiz(intel,
1041 intel_renderbuffer(irb->wrapped_depth));
1042
1043 return false;
1044 }
1045
1046 bool
1047 intel_renderbuffer_resolve_depth(struct intel_context *intel,
1048 struct intel_renderbuffer *irb)
1049 {
1050 if (irb->mt)
1051 return intel_miptree_slice_resolve_depth(intel,
1052 irb->mt,
1053 irb->mt_level,
1054 irb->mt_layer);
1055
1056 if (irb->wrapped_depth)
1057 return intel_renderbuffer_resolve_depth(intel,
1058 intel_renderbuffer(irb->wrapped_depth));
1059
1060 return false;
1061 }
1062
1063 /**
1064 * Do one-time context initializations related to GL_EXT_framebuffer_object.
1065 * Hook in device driver functions.
1066 */
1067 void
1068 intel_fbo_init(struct intel_context *intel)
1069 {
1070 intel->ctx.Driver.NewFramebuffer = intel_new_framebuffer;
1071 intel->ctx.Driver.NewRenderbuffer = intel_new_renderbuffer;
1072 intel->ctx.Driver.MapRenderbuffer = intel_map_renderbuffer;
1073 intel->ctx.Driver.UnmapRenderbuffer = intel_unmap_renderbuffer;
1074 intel->ctx.Driver.BindFramebuffer = intel_bind_framebuffer;
1075 intel->ctx.Driver.FramebufferRenderbuffer = intel_framebuffer_renderbuffer;
1076 intel->ctx.Driver.RenderTexture = intel_render_texture;
1077 intel->ctx.Driver.FinishRenderTexture = intel_finish_render_texture;
1078 intel->ctx.Driver.ResizeBuffers = intel_resize_buffers;
1079 intel->ctx.Driver.ValidateFramebuffer = intel_validate_framebuffer;
1080 intel->ctx.Driver.BlitFramebuffer = intel_blit_framebuffer;
1081
1082 #if FEATURE_OES_EGL_image
1083 intel->ctx.Driver.EGLImageTargetRenderbufferStorage =
1084 intel_image_target_renderbuffer_storage;
1085 #endif
1086 }