32 and z24s8 softpipe buffers
[mesa.git] / src / mesa / drivers / dri / i915tex / 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 "imports.h"
30 #include "mtypes.h"
31 #include "fbobject.h"
32 #include "framebuffer.h"
33 #include "renderbuffer.h"
34 #include "context.h"
35 #include "texformat.h"
36 #include "texrender.h"
37
38 #include "intel_context.h"
39 #include "intel_buffers.h"
40 #include "intel_depthstencil.h"
41 #include "intel_fbo.h"
42 #include "intel_mipmap_tree.h"
43 #include "intel_regions.h"
44 #include "intel_span.h"
45
46
47 #define FILE_DEBUG_FLAG DEBUG_FBO
48
49 #define INTEL_RB_CLASS 0x12345678
50
51
52 /* XXX FBO: move this to intel_context.h (inlined) */
53 /**
54 * Return a gl_renderbuffer ptr casted to intel_renderbuffer.
55 * NULL will be returned if the rb isn't really an intel_renderbuffer.
56 * This is determiend by checking the ClassID.
57 */
58 struct intel_renderbuffer *
59 intel_renderbuffer(struct gl_renderbuffer *rb)
60 {
61 struct intel_renderbuffer *irb = (struct intel_renderbuffer *) rb;
62 if (irb && irb->Base.ClassID == INTEL_RB_CLASS) {
63 /*_mesa_warning(NULL, "Returning non-intel Rb\n");*/
64 return irb;
65 }
66 else
67 return NULL;
68 }
69
70
71 struct intel_renderbuffer *
72 intel_get_renderbuffer(struct gl_framebuffer *fb, GLuint attIndex)
73 {
74 return intel_renderbuffer(fb->Attachment[attIndex].Renderbuffer);
75 }
76
77
78 void
79 intel_flip_renderbuffers(struct intel_framebuffer *intel_fb)
80 {
81 int current_page = intel_fb->pf_current_page;
82 int next_page = (current_page + 1) % intel_fb->pf_num_pages;
83 struct gl_renderbuffer *tmp_rb;
84
85 /* Exchange renderbuffers if necessary but make sure their reference counts
86 * are preserved.
87 */
88 if (intel_fb->color_rb[current_page] &&
89 intel_fb->Base.Attachment[BUFFER_FRONT_LEFT].Renderbuffer !=
90 &intel_fb->color_rb[current_page]->Base) {
91 tmp_rb = NULL;
92 _mesa_reference_renderbuffer(&tmp_rb,
93 intel_fb->Base.Attachment[BUFFER_FRONT_LEFT].Renderbuffer);
94 tmp_rb = &intel_fb->color_rb[current_page]->Base;
95 _mesa_reference_renderbuffer(
96 &intel_fb->Base.Attachment[BUFFER_FRONT_LEFT].Renderbuffer, tmp_rb);
97 _mesa_reference_renderbuffer(&tmp_rb, NULL);
98 }
99
100 if (intel_fb->color_rb[next_page] &&
101 intel_fb->Base.Attachment[BUFFER_BACK_LEFT].Renderbuffer !=
102 &intel_fb->color_rb[next_page]->Base) {
103 tmp_rb = NULL;
104 _mesa_reference_renderbuffer(&tmp_rb,
105 intel_fb->Base.Attachment[BUFFER_BACK_LEFT].Renderbuffer);
106 tmp_rb = &intel_fb->color_rb[next_page]->Base;
107 _mesa_reference_renderbuffer(
108 &intel_fb->Base.Attachment[BUFFER_BACK_LEFT].Renderbuffer, tmp_rb);
109 _mesa_reference_renderbuffer(&tmp_rb, NULL);
110 }
111 }
112
113
114 struct intel_region *
115 intel_get_rb_region(struct gl_framebuffer *fb, GLuint attIndex)
116 {
117 struct intel_renderbuffer *irb = intel_get_renderbuffer(fb, attIndex);
118
119 if (irb)
120 return irb->region;
121 else
122 return NULL;
123 }
124
125
126
127 /**
128 * Create a new framebuffer object.
129 */
130 static struct gl_framebuffer *
131 intel_new_framebuffer(GLcontext * ctx, GLuint name)
132 {
133 /* Only drawable state in intel_framebuffer at this time, just use Mesa's
134 * class
135 */
136 return _mesa_new_framebuffer(ctx, name);
137 }
138
139
140 static void
141 intel_delete_renderbuffer(struct gl_renderbuffer *rb)
142 {
143 GET_CURRENT_CONTEXT(ctx);
144 struct intel_context *intel = intel_context(ctx);
145 struct intel_renderbuffer *irb = intel_renderbuffer(rb);
146
147 ASSERT(irb);
148
149 if (irb->PairedStencil || irb->PairedDepth) {
150 intel_unpair_depth_stencil(ctx, irb);
151 }
152
153 if (intel && irb->region) {
154 intel_region_release(&irb->region);
155 }
156
157 _mesa_free(irb);
158 }
159
160
161
162 /**
163 * Return a pointer to a specific pixel in a renderbuffer.
164 */
165 static void *
166 intel_get_pointer(GLcontext * ctx, struct gl_renderbuffer *rb,
167 GLint x, GLint y)
168 {
169 /* By returning NULL we force all software rendering to go through
170 * the span routines.
171 */
172 return NULL;
173 }
174
175
176
177 /**
178 * Called via glRenderbufferStorageEXT() to set the format and allocate
179 * storage for a user-created (or priv buffer) renderbuffer.
180 */
181 static GLboolean
182 intel_alloc_renderbuffer_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
183 GLenum internalFormat,
184 GLuint width, GLuint height)
185 {
186 struct intel_context *intel = intel_context(ctx);
187 struct intel_renderbuffer *irb = intel_renderbuffer(rb);
188 GLboolean softwareBuffer = GL_FALSE;
189 int cpp;
190
191 switch (internalFormat) {
192 case GL_R3_G3_B2:
193 case GL_RGB4:
194 case GL_RGB5:
195 rb->_ActualFormat = GL_RGB5;
196 rb->DataType = GL_UNSIGNED_BYTE;
197 rb->RedBits = 5;
198 rb->GreenBits = 6;
199 rb->BlueBits = 5;
200 cpp = 2;
201 break;
202 case GL_RGB:
203 case GL_RGB8:
204 case GL_RGB10:
205 case GL_RGB12:
206 case GL_RGB16:
207 case GL_RGBA:
208 case GL_RGBA2:
209 case GL_RGBA4:
210 case GL_RGB5_A1:
211 case GL_RGBA8:
212 case GL_RGB10_A2:
213 case GL_RGBA12:
214 case GL_RGBA16:
215 rb->_ActualFormat = GL_RGBA8;
216 rb->DataType = GL_UNSIGNED_BYTE;
217 rb->RedBits = 8;
218 rb->GreenBits = 8;
219 rb->BlueBits = 8;
220 rb->AlphaBits = 8;
221 cpp = 4;
222 break;
223 case GL_STENCIL_INDEX:
224 case GL_STENCIL_INDEX1_EXT:
225 case GL_STENCIL_INDEX4_EXT:
226 case GL_STENCIL_INDEX8_EXT:
227 case GL_STENCIL_INDEX16_EXT:
228 /* alloc a depth+stencil buffer */
229 rb->_ActualFormat = GL_DEPTH24_STENCIL8_EXT;
230 rb->DataType = GL_UNSIGNED_INT_24_8_EXT;
231 rb->StencilBits = 8;
232 cpp = 4;
233 break;
234 case GL_DEPTH_COMPONENT16:
235 rb->_ActualFormat = GL_DEPTH_COMPONENT16;
236 rb->DataType = GL_UNSIGNED_SHORT;
237 rb->DepthBits = 16;
238 cpp = 2;
239 break;
240 case GL_DEPTH_COMPONENT:
241 case GL_DEPTH_COMPONENT24:
242 case GL_DEPTH_COMPONENT32:
243 rb->_ActualFormat = GL_DEPTH24_STENCIL8_EXT;
244 rb->DataType = GL_UNSIGNED_INT_24_8_EXT;
245 rb->DepthBits = 24;
246 cpp = 4;
247 break;
248 case GL_DEPTH_STENCIL_EXT:
249 case GL_DEPTH24_STENCIL8_EXT:
250 rb->_ActualFormat = GL_DEPTH24_STENCIL8_EXT;
251 rb->DataType = GL_UNSIGNED_INT_24_8_EXT;
252 rb->DepthBits = 24;
253 rb->StencilBits = 8;
254 cpp = 4;
255 break;
256 default:
257 _mesa_problem(ctx,
258 "Unexpected format (%x) in intel_alloc_renderbuffer_storage", internalFormat);
259 return GL_FALSE;
260 }
261
262 intelFlush(ctx);
263
264 /* free old region */
265 if (irb->region) {
266 intel_region_release(&irb->region);
267 }
268
269 /* allocate new memory region/renderbuffer */
270 if (softwareBuffer) {
271 return _mesa_soft_renderbuffer_storage(ctx, rb, internalFormat,
272 width, height);
273 }
274 else {
275 /* Choose a pitch to match hardware requirements:
276 */
277 GLuint pitch = ((cpp * width + 63) & ~63) / cpp;
278
279 /* alloc hardware renderbuffer */
280 DBG("Allocating %d x %d Intel RBO (pitch %d)\n", width,
281 height, pitch);
282
283 irb->region = intel_region_alloc(intel->intelScreen, cpp, pitch, height);
284 if (!irb->region)
285 return GL_FALSE; /* out of memory? */
286
287 ASSERT(irb->region->buffer);
288
289 rb->Width = width;
290 rb->Height = height;
291
292 #if 1
293 /* update the surface's size too */
294 rb->surface->width = width;
295 rb->surface->height = height;
296 #endif
297
298 /* This sets the Get/PutRow/Value functions */
299 intel_set_span_functions(&irb->Base);
300
301 return GL_TRUE;
302 }
303 }
304
305
306
307 /**
308 * Called for each hardware renderbuffer when a _window_ is resized.
309 * Just update fields.
310 * Not used for user-created renderbuffers!
311 */
312 static GLboolean
313 intel_alloc_window_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
314 GLenum internalFormat, GLuint width, GLuint height)
315 {
316 ASSERT(rb->Name == 0);
317 rb->Width = width;
318 rb->Height = height;
319 rb->_ActualFormat = internalFormat;
320
321 return GL_TRUE;
322 }
323
324 static void
325 intel_resize_buffers(GLcontext *ctx, struct gl_framebuffer *fb,
326 GLuint width, GLuint height)
327 {
328 struct intel_framebuffer *intel_fb = (struct intel_framebuffer*)fb;
329 int i;
330
331 _mesa_resize_framebuffer(ctx, fb, width, height);
332
333 fb->Initialized = GL_TRUE; /* XXX remove someday */
334
335 if (fb->Name != 0) {
336 return;
337 }
338
339 /* Make sure all window system renderbuffers are up to date */
340 for (i = 0; i < 3; i++) {
341 struct gl_renderbuffer *rb = &intel_fb->color_rb[i]->Base;
342
343 /* only resize if size is changing */
344 if (rb && (rb->Width != width || rb->Height != height)) {
345 rb->AllocStorage(ctx, rb, rb->InternalFormat, width, height);
346 }
347 }
348 }
349
350 static GLboolean
351 intel_nop_alloc_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
352 GLenum internalFormat, GLuint width, GLuint height)
353 {
354 _mesa_problem(ctx, "intel_op_alloc_storage should never be called.");
355 return GL_FALSE;
356 }
357
358
359
360 /**
361 * Create a new intel_renderbuffer which corresponds to an on-screen window,
362 * not a user-created renderbuffer.
363 * \param width the screen width
364 * \param height the screen height
365 */
366 struct intel_renderbuffer *
367 intel_create_renderbuffer(GLenum intFormat, GLsizei width, GLsizei height,
368 int offset, int pitch, int cpp, void *map)
369 {
370 GET_CURRENT_CONTEXT(ctx);
371
372 struct intel_renderbuffer *irb;
373 const GLuint name = 0;
374
375 irb = CALLOC_STRUCT(intel_renderbuffer);
376 if (!irb) {
377 _mesa_error(ctx, GL_OUT_OF_MEMORY, "creating renderbuffer");
378 return NULL;
379 }
380
381 _mesa_init_renderbuffer(&irb->Base, name);
382 irb->Base.ClassID = INTEL_RB_CLASS;
383
384 switch (intFormat) {
385 case GL_RGB5:
386 irb->Base._ActualFormat = GL_RGB5;
387 irb->Base._BaseFormat = GL_RGBA;
388 irb->Base.RedBits = 5;
389 irb->Base.GreenBits = 6;
390 irb->Base.BlueBits = 5;
391 irb->Base.DataType = GL_UNSIGNED_BYTE;
392 cpp = 2;
393 break;
394 case GL_RGBA8:
395 irb->Base._ActualFormat = GL_RGBA8;
396 irb->Base._BaseFormat = GL_RGBA;
397 irb->Base.RedBits = 8;
398 irb->Base.GreenBits = 8;
399 irb->Base.BlueBits = 8;
400 irb->Base.AlphaBits = 8;
401 irb->Base.DataType = GL_UNSIGNED_BYTE;
402 cpp = 4;
403 break;
404 case GL_STENCIL_INDEX8_EXT:
405 irb->Base._ActualFormat = GL_STENCIL_INDEX8_EXT;
406 irb->Base._BaseFormat = GL_STENCIL_INDEX;
407 irb->Base.StencilBits = 8;
408 irb->Base.DataType = GL_UNSIGNED_BYTE;
409 cpp = 1;
410 break;
411 case GL_DEPTH_COMPONENT16:
412 irb->Base._ActualFormat = GL_DEPTH_COMPONENT16;
413 irb->Base._BaseFormat = GL_DEPTH_COMPONENT;
414 irb->Base.DepthBits = 16;
415 irb->Base.DataType = GL_UNSIGNED_SHORT;
416 cpp = 2;
417 break;
418 case GL_DEPTH_COMPONENT24:
419 irb->Base._ActualFormat = GL_DEPTH24_STENCIL8_EXT;
420 irb->Base._BaseFormat = GL_DEPTH_COMPONENT;
421 irb->Base.DepthBits = 24;
422 irb->Base.DataType = GL_UNSIGNED_INT;
423 cpp = 4;
424 break;
425 case GL_DEPTH24_STENCIL8_EXT:
426 irb->Base._ActualFormat = GL_DEPTH24_STENCIL8_EXT;
427 irb->Base._BaseFormat = GL_DEPTH_STENCIL_EXT;
428 irb->Base.DepthBits = 24;
429 irb->Base.StencilBits = 8;
430 irb->Base.DataType = GL_UNSIGNED_INT_24_8_EXT;
431 cpp = 4;
432 break;
433 default:
434 _mesa_problem(NULL,
435 "Unexpected intFormat in intel_create_renderbuffer");
436 return NULL;
437 }
438
439 irb->Base.InternalFormat = intFormat;
440
441 /* intel-specific methods */
442 irb->Base.Delete = intel_delete_renderbuffer;
443 irb->Base.AllocStorage = intel_alloc_window_storage;
444 irb->Base.GetPointer = intel_get_pointer;
445 /* This sets the Get/PutRow/Value functions */
446 intel_set_span_functions(&irb->Base);
447
448 irb->pfMap = map;
449 irb->pfPitch = pitch / cpp; /* in pixels */
450
451 #if 00
452 irb->region = intel_region_create_static(intel,
453 DRM_MM_TT,
454 offset, map, cpp, width, height);
455 #endif
456
457 return irb;
458 }
459
460
461 /**
462 * Create a new renderbuffer which corresponds to an X window buffer
463 * (color, depth, stencil, etc) - not a user-created GL renderbuffer.
464 * The internal format is set at creation time and does not change.
465 */
466 struct gl_renderbuffer *
467 intel_new_renderbuffer_fb(GLcontext * ctx, GLuint intFormat)
468 {
469 struct intel_renderbuffer *irb;
470
471 irb = CALLOC_STRUCT(intel_renderbuffer);
472 if (!irb) {
473 _mesa_error(ctx, GL_OUT_OF_MEMORY, "creating renderbuffer");
474 return NULL;
475 }
476
477 _mesa_init_renderbuffer(&irb->Base, 0);
478 irb->Base.ClassID = INTEL_RB_CLASS;
479 irb->Base.InternalFormat = intFormat;
480
481 /* intel-specific methods */
482 irb->Base.Delete = intel_delete_renderbuffer;
483 irb->Base.AllocStorage = intel_alloc_renderbuffer_storage;
484 irb->Base.GetPointer = intel_get_pointer;
485 /* span routines set in alloc_storage function */
486
487 irb->Base.surface = intel_new_surface(intFormat);
488 irb->Base.surface->rb = irb;
489
490 return &irb->Base;
491 }
492
493 /**
494 * Create a new renderbuffer object.
495 * Typically called via glBindRenderbufferEXT().
496 */
497 static struct gl_renderbuffer *
498 intel_new_renderbuffer(GLcontext * ctx, GLuint name)
499 {
500 /*struct intel_context *intel = intel_context(ctx); */
501 struct intel_renderbuffer *irb;
502
503 irb = CALLOC_STRUCT(intel_renderbuffer);
504 if (!irb) {
505 _mesa_error(ctx, GL_OUT_OF_MEMORY, "creating renderbuffer");
506 return NULL;
507 }
508
509 _mesa_init_renderbuffer(&irb->Base, name);
510 irb->Base.ClassID = INTEL_RB_CLASS;
511
512 /* intel-specific methods */
513 irb->Base.Delete = intel_delete_renderbuffer;
514 irb->Base.AllocStorage = intel_alloc_renderbuffer_storage;
515 irb->Base.GetPointer = intel_get_pointer;
516 /* span routines set in alloc_storage function */
517
518 irb->Base.surface = intel_new_surface(0 /*unknown format*/);
519 irb->Base.surface->rb = irb;
520
521 return &irb->Base;
522 }
523
524
525 /**
526 * Called via glBindFramebufferEXT().
527 */
528 static void
529 intel_bind_framebuffer(GLcontext * ctx, GLenum target,
530 struct gl_framebuffer *fb, struct gl_framebuffer *fbread)
531 {
532 if (target == GL_FRAMEBUFFER_EXT || target == GL_DRAW_FRAMEBUFFER_EXT) {
533 intel_draw_buffer(ctx, fb);
534 /* Integer depth range depends on depth buffer bits */
535 ctx->Driver.DepthRange(ctx, ctx->Viewport.Near, ctx->Viewport.Far);
536 }
537 else {
538 /* don't need to do anything if target == GL_READ_FRAMEBUFFER_EXT */
539 }
540 }
541
542
543 /**
544 * Called via glFramebufferRenderbufferEXT().
545 */
546 static void
547 intel_framebuffer_renderbuffer(GLcontext * ctx,
548 struct gl_framebuffer *fb,
549 GLenum attachment, struct gl_renderbuffer *rb)
550 {
551 DBG("Intel FramebufferRenderbuffer %u %u\n", fb->Name, rb ? rb->Name : 0);
552
553 intelFlush(ctx);
554
555 _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb);
556 intel_draw_buffer(ctx, fb);
557 }
558
559
560 /**
561 * When glFramebufferTexture[123]D is called this function sets up the
562 * gl_renderbuffer wrapper around the texture image.
563 * This will have the region info needed for hardware rendering.
564 */
565 static struct intel_renderbuffer *
566 intel_wrap_texture(GLcontext * ctx, struct gl_texture_image *texImage)
567 {
568 const GLuint name = ~0; /* not significant, but distinct for debugging */
569 struct intel_renderbuffer *irb;
570
571 /* make an intel_renderbuffer to wrap the texture image */
572 irb = CALLOC_STRUCT(intel_renderbuffer);
573 if (!irb) {
574 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glFramebufferTexture");
575 return NULL;
576 }
577
578 _mesa_init_renderbuffer(&irb->Base, name);
579 irb->Base.ClassID = INTEL_RB_CLASS;
580
581 if (texImage->TexFormat == &_mesa_texformat_argb8888) {
582 irb->Base._ActualFormat = GL_RGBA8;
583 irb->Base._BaseFormat = GL_RGBA;
584 DBG("Render to RGBA8 texture OK\n");
585 }
586 else if (texImage->TexFormat == &_mesa_texformat_rgb565) {
587 irb->Base._ActualFormat = GL_RGB5;
588 irb->Base._BaseFormat = GL_RGB;
589 DBG("Render to RGB5 texture OK\n");
590 }
591 else if (texImage->TexFormat == &_mesa_texformat_z16) {
592 irb->Base._ActualFormat = GL_DEPTH_COMPONENT16;
593 irb->Base._BaseFormat = GL_DEPTH_COMPONENT;
594 DBG("Render to DEPTH16 texture OK\n");
595 }
596 else {
597 DBG("Render to texture BAD FORMAT %d\n",
598 texImage->TexFormat->MesaFormat);
599 _mesa_free(irb);
600 return NULL;
601 }
602
603 irb->Base.InternalFormat = irb->Base._ActualFormat;
604 irb->Base.Width = texImage->Width;
605 irb->Base.Height = texImage->Height;
606 irb->Base.DataType = GL_UNSIGNED_BYTE; /* FBO XXX fix */
607 irb->Base.RedBits = texImage->TexFormat->RedBits;
608 irb->Base.GreenBits = texImage->TexFormat->GreenBits;
609 irb->Base.BlueBits = texImage->TexFormat->BlueBits;
610 irb->Base.AlphaBits = texImage->TexFormat->AlphaBits;
611 irb->Base.DepthBits = texImage->TexFormat->DepthBits;
612
613 irb->Base.Delete = intel_delete_renderbuffer;
614 irb->Base.AllocStorage = intel_nop_alloc_storage;
615 intel_set_span_functions(&irb->Base);
616
617 irb->RenderToTexture = GL_TRUE;
618
619 return irb;
620 }
621
622
623 /**
624 * Called by glFramebufferTexture[123]DEXT() (and other places) to
625 * prepare for rendering into texture memory. This might be called
626 * many times to choose different texture levels, cube faces, etc
627 * before intel_finish_render_texture() is ever called.
628 */
629 static void
630 intel_render_texture(GLcontext * ctx,
631 struct gl_framebuffer *fb,
632 struct gl_renderbuffer_attachment *att)
633 {
634 struct gl_texture_image *newImage
635 = att->Texture->Image[att->CubeMapFace][att->TextureLevel];
636 struct intel_renderbuffer *irb = intel_renderbuffer(att->Renderbuffer);
637 struct intel_texture_image *intel_image;
638 GLuint imageOffset;
639
640 (void) fb;
641
642 ASSERT(newImage);
643
644 if (!irb) {
645 irb = intel_wrap_texture(ctx, newImage);
646 if (irb) {
647 /* bind the wrapper to the attachment point */
648 _mesa_reference_renderbuffer(&att->Renderbuffer, &irb->Base);
649 }
650 else {
651 /* fallback to software rendering */
652 _mesa_render_texture(ctx, fb, att);
653 return;
654 }
655 }
656
657 DBG("Begin render texture tid %x tex=%u w=%d h=%d refcount=%d\n",
658 _glthread_GetID(),
659 att->Texture->Name, newImage->Width, newImage->Height,
660 irb->Base.RefCount);
661
662 /* point the renderbufer's region to the texture image region */
663 intel_image = intel_texture_image(newImage);
664 if (irb->region != intel_image->mt->region) {
665 if (irb->region)
666 intel_region_release(&irb->region);
667 intel_region_reference(&irb->region, intel_image->mt->region);
668 }
669
670 /* compute offset of the particular 2D image within the texture region */
671 imageOffset = intel_miptree_image_offset(intel_image->mt,
672 att->CubeMapFace,
673 att->TextureLevel);
674
675 if (att->Texture->Target == GL_TEXTURE_3D) {
676 const GLuint *offsets = intel_miptree_depth_offsets(intel_image->mt,
677 att->TextureLevel);
678 imageOffset += offsets[att->Zoffset];
679 }
680
681 /* store that offset in the region */
682 intel_image->mt->region->draw_offset = imageOffset;
683
684 /* update drawing region, etc */
685 intel_draw_buffer(ctx, fb);
686 }
687
688
689 /**
690 * Called by Mesa when rendering to a texture is done.
691 */
692 static void
693 intel_finish_render_texture(GLcontext * ctx,
694 struct gl_renderbuffer_attachment *att)
695 {
696 struct intel_renderbuffer *irb = intel_renderbuffer(att->Renderbuffer);
697
698 DBG("End render texture (tid %x) tex %u\n", _glthread_GetID(), att->Texture->Name);
699
700 if (irb) {
701 /* just release the region */
702 intel_region_release(&irb->region);
703 }
704 else if (att->Renderbuffer) {
705 /* software fallback */
706 _mesa_finish_render_texture(ctx, att);
707 /* XXX FBO: Need to unmap the buffer (or in intelSpanRenderStart???) */
708 }
709 }
710
711
712 /**
713 * Do one-time context initializations related to GL_EXT_framebuffer_object.
714 * Hook in device driver functions.
715 */
716 void
717 intel_fbo_init(struct intel_context *intel)
718 {
719 intel->ctx.Driver.NewFramebuffer = intel_new_framebuffer;
720 intel->ctx.Driver.NewRenderbuffer = intel_new_renderbuffer;
721 intel->ctx.Driver.BindFramebuffer = intel_bind_framebuffer;
722 intel->ctx.Driver.FramebufferRenderbuffer = intel_framebuffer_renderbuffer;
723 intel->ctx.Driver.RenderTexture = intel_render_texture;
724 intel->ctx.Driver.FinishRenderTexture = intel_finish_render_texture;
725 intel->ctx.Driver.ResizeBuffers = intel_resize_buffers;
726 }