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