9475704121c8595c28ebb06b4594cd6725651f02
[mesa.git] / src / mesa / state_tracker / st_manager.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 7.9
4 *
5 * Copyright (C) 2010 LunarG Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 *
24 * Authors:
25 * Chia-I Wu <olv@lunarg.com>
26 */
27
28 #include "state_tracker/st_api.h"
29
30 #include "pipe/p_context.h"
31 #include "pipe/p_screen.h"
32 #include "util/u_format.h"
33 #include "util/u_pointer.h"
34 #include "util/u_inlines.h"
35 #include "util/u_atomic.h"
36
37 #include "main/mtypes.h"
38 #include "main/context.h"
39 #include "main/texobj.h"
40 #include "main/teximage.h"
41 #include "main/texstate.h"
42 #include "main/texfetch.h"
43 #include "main/fbobject.h"
44 #include "main/framebuffer.h"
45 #include "main/renderbuffer.h"
46 #include "st_texture.h"
47
48 #include "st_context.h"
49 #include "st_format.h"
50 #include "st_cb_fbo.h"
51 #include "st_manager.h"
52
53 /* these functions are defined in st_context.c */
54 struct st_context *
55 st_create_context(struct pipe_context *pipe,
56 const __GLcontextModes *visual,
57 struct st_context *share);
58 void st_destroy_context(struct st_context *st);
59 void st_flush(struct st_context *st, uint pipeFlushFlags,
60 struct pipe_fence_handle **fence);
61
62 /**
63 * Map an attachment to a buffer index.
64 */
65 static INLINE gl_buffer_index
66 attachment_to_buffer_index(enum st_attachment_type statt)
67 {
68 gl_buffer_index index;
69
70 switch (statt) {
71 case ST_ATTACHMENT_FRONT_LEFT:
72 index = BUFFER_FRONT_LEFT;
73 break;
74 case ST_ATTACHMENT_BACK_LEFT:
75 index = BUFFER_BACK_LEFT;
76 break;
77 case ST_ATTACHMENT_FRONT_RIGHT:
78 index = BUFFER_FRONT_RIGHT;
79 break;
80 case ST_ATTACHMENT_BACK_RIGHT:
81 index = BUFFER_BACK_RIGHT;
82 break;
83 case ST_ATTACHMENT_DEPTH_STENCIL:
84 index = BUFFER_DEPTH;
85 break;
86 case ST_ATTACHMENT_ACCUM:
87 index = BUFFER_ACCUM;
88 break;
89 case ST_ATTACHMENT_SAMPLE:
90 default:
91 index = BUFFER_COUNT;
92 break;
93 }
94
95 return index;
96 }
97
98 /**
99 * Map a buffer index to an attachment.
100 */
101 static INLINE enum st_attachment_type
102 buffer_index_to_attachment(gl_buffer_index index)
103 {
104 enum st_attachment_type statt;
105
106 switch (index) {
107 case BUFFER_FRONT_LEFT:
108 statt = ST_ATTACHMENT_FRONT_LEFT;
109 break;
110 case BUFFER_BACK_LEFT:
111 statt = ST_ATTACHMENT_BACK_LEFT;
112 break;
113 case BUFFER_FRONT_RIGHT:
114 statt = ST_ATTACHMENT_FRONT_RIGHT;
115 break;
116 case BUFFER_BACK_RIGHT:
117 statt = ST_ATTACHMENT_BACK_RIGHT;
118 break;
119 case BUFFER_DEPTH:
120 statt = ST_ATTACHMENT_DEPTH_STENCIL;
121 break;
122 case BUFFER_ACCUM:
123 statt = ST_ATTACHMENT_ACCUM;
124 break;
125 default:
126 statt = ST_ATTACHMENT_INVALID;
127 break;
128 }
129
130 return statt;
131 }
132
133 /**
134 * Validate a framebuffer and update the states of the context.
135 */
136 static void
137 st_framebuffer_validate(struct st_framebuffer *stfb, struct st_context *st)
138 {
139 struct pipe_screen *screen = st->pipe->screen;
140 struct pipe_texture *textures[ST_ATTACHMENT_COUNT];
141 uint width, height;
142 unsigned i;
143 boolean changed = FALSE;
144
145 if (!p_atomic_read(&stfb->revalidate))
146 return;
147
148 /* validate the fb */
149 if (!stfb->iface->validate(stfb->iface, stfb->statts, stfb->num_statts, textures))
150 return;
151
152 width = stfb->Base.Width;
153 height = stfb->Base.Height;
154
155 for (i = 0; i < stfb->num_statts; i++) {
156 struct st_renderbuffer *strb;
157 struct pipe_surface *ps;
158 gl_buffer_index idx;
159
160 if (!textures[i])
161 continue;
162
163 idx = attachment_to_buffer_index(stfb->statts[i]);
164 if (idx >= BUFFER_COUNT) {
165 pipe_texture_reference(&textures[i], NULL);
166 continue;
167 }
168
169 strb = st_renderbuffer(stfb->Base.Attachment[idx].Renderbuffer);
170 assert(strb);
171 if (strb->texture == textures[i]) {
172 pipe_texture_reference(&textures[i], NULL);
173 continue;
174 }
175
176 ps = screen->get_tex_surface(screen, textures[i], 0, 0, 0,
177 PIPE_BUFFER_USAGE_GPU_READ | PIPE_BUFFER_USAGE_GPU_WRITE);
178 if (ps) {
179 pipe_surface_reference(&strb->surface, ps);
180 pipe_texture_reference(&strb->texture, ps->texture);
181 /* ownership transfered */
182 pipe_surface_reference(&ps, NULL);
183
184 changed = TRUE;
185
186 strb->Base.Width = strb->surface->width;
187 strb->Base.Height = strb->surface->height;
188
189 width = strb->Base.Width;
190 height = strb->Base.Height;
191 }
192
193 pipe_texture_reference(&textures[i], NULL);
194 }
195
196 if (changed) {
197 st->dirty.st |= ST_NEW_FRAMEBUFFER;
198 _mesa_resize_framebuffer(st->ctx, &stfb->Base, width, height);
199
200 assert(stfb->Base.Width == width);
201 assert(stfb->Base.Height == height);
202 }
203
204 p_atomic_set(&stfb->revalidate, FALSE);
205 }
206
207 /**
208 * Update the attachments to validate.
209 */
210 static void
211 st_framebuffer_update_attachments(struct st_framebuffer *stfb)
212 {
213 gl_buffer_index idx;
214
215 stfb->num_statts = 0;
216 for (idx = 0; idx < BUFFER_COUNT; idx++) {
217 struct st_renderbuffer *strb;
218 enum st_attachment_type statt;
219
220 strb = st_renderbuffer(stfb->Base.Attachment[idx].Renderbuffer);
221 if (!strb || strb->software)
222 continue;
223
224 statt = buffer_index_to_attachment(idx);
225 if (statt != ST_ATTACHMENT_INVALID &&
226 st_visual_have_buffers(stfb->iface->visual, 1 << statt))
227 stfb->statts[stfb->num_statts++] = statt;
228 }
229
230 p_atomic_set(&stfb->revalidate, TRUE);
231 }
232
233 /**
234 * Add a renderbuffer to the framebuffer.
235 */
236 static boolean
237 st_framebuffer_add_renderbuffer(struct st_framebuffer *stfb,
238 gl_buffer_index idx)
239 {
240 struct gl_renderbuffer *rb;
241 enum pipe_format format;
242 int samples;
243 boolean sw;
244
245 /* do not distinguish depth/stencil buffers */
246 if (idx == BUFFER_STENCIL)
247 idx = BUFFER_DEPTH;
248
249 switch (idx) {
250 case BUFFER_DEPTH:
251 format = stfb->iface->visual->depth_stencil_format;
252 sw = FALSE;
253 break;
254 case BUFFER_ACCUM:
255 format = stfb->iface->visual->accum_format;
256 sw = TRUE;
257 break;
258 default:
259 format = stfb->iface->visual->color_format;
260 sw = FALSE;
261 break;
262 }
263
264 if (format == PIPE_FORMAT_NONE)
265 return FALSE;
266
267 samples = stfb->iface->visual->samples;
268 if (!samples)
269 samples = st_get_msaa();
270
271 rb = st_new_renderbuffer_fb(format, samples, sw);
272 if (!rb)
273 return FALSE;
274
275 if (idx != BUFFER_DEPTH) {
276 _mesa_add_renderbuffer(&stfb->Base, idx, rb);
277 }
278 else {
279 if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_ZS, 0))
280 _mesa_add_renderbuffer(&stfb->Base, BUFFER_DEPTH, rb);
281 if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_ZS, 1))
282 _mesa_add_renderbuffer(&stfb->Base, BUFFER_STENCIL, rb);
283 }
284
285 return TRUE;
286 }
287
288 /**
289 * Intialize a __GLcontextModes from a visual.
290 */
291 static void
292 st_visual_to_context_mode(const struct st_visual *visual,
293 __GLcontextModes *mode)
294 {
295 memset(mode, 0, sizeof(*mode));
296
297 if (st_visual_have_buffers(visual, ST_ATTACHMENT_BACK_LEFT_MASK))
298 mode->doubleBufferMode = GL_TRUE;
299 if (st_visual_have_buffers(visual,
300 ST_ATTACHMENT_FRONT_RIGHT_MASK | ST_ATTACHMENT_BACK_RIGHT_MASK))
301 mode->stereoMode = GL_TRUE;
302
303 if (visual->color_format != PIPE_FORMAT_NONE) {
304 mode->rgbMode = GL_TRUE;
305
306 mode->redBits =
307 util_format_get_component_bits(visual->color_format,
308 UTIL_FORMAT_COLORSPACE_RGB, 0);
309 mode->greenBits =
310 util_format_get_component_bits(visual->color_format,
311 UTIL_FORMAT_COLORSPACE_RGB, 1);
312 mode->blueBits =
313 util_format_get_component_bits(visual->color_format,
314 UTIL_FORMAT_COLORSPACE_RGB, 2);
315 mode->alphaBits =
316 util_format_get_component_bits(visual->color_format,
317 UTIL_FORMAT_COLORSPACE_RGB, 3);
318
319 mode->rgbBits = mode->redBits +
320 mode->greenBits + mode->blueBits + mode->alphaBits;
321 }
322
323 if (visual->depth_stencil_format != PIPE_FORMAT_NONE) {
324 mode->haveDepthBuffer = GL_TRUE;
325 mode->haveStencilBuffer = GL_TRUE;
326
327 mode->depthBits =
328 util_format_get_component_bits(visual->depth_stencil_format,
329 UTIL_FORMAT_COLORSPACE_ZS, 0);
330 mode->stencilBits =
331 util_format_get_component_bits(visual->depth_stencil_format,
332 UTIL_FORMAT_COLORSPACE_ZS, 1);
333 }
334
335 if (visual->accum_format != PIPE_FORMAT_NONE) {
336 mode->haveAccumBuffer = GL_TRUE;
337
338 mode->accumRedBits =
339 util_format_get_component_bits(visual->accum_format,
340 UTIL_FORMAT_COLORSPACE_RGB, 0);
341 mode->accumGreenBits =
342 util_format_get_component_bits(visual->accum_format,
343 UTIL_FORMAT_COLORSPACE_RGB, 1);
344 mode->accumBlueBits =
345 util_format_get_component_bits(visual->accum_format,
346 UTIL_FORMAT_COLORSPACE_RGB, 2);
347 mode->accumAlphaBits =
348 util_format_get_component_bits(visual->accum_format,
349 UTIL_FORMAT_COLORSPACE_RGB, 3);
350 }
351
352 if (visual->samples) {
353 mode->sampleBuffers = 1;
354 mode->samples = visual->samples;
355 }
356 }
357
358 /**
359 * Determine the default draw or read buffer from a visual.
360 */
361 static void
362 st_visual_to_default_buffer(const struct st_visual *visual,
363 GLenum *buffer, GLint *index)
364 {
365 enum st_attachment_type statt;
366 GLenum buf;
367 gl_buffer_index idx;
368
369 statt = visual->render_buffer;
370 /* do nothing if an invalid render buffer is specified */
371 if (statt == ST_ATTACHMENT_INVALID ||
372 !st_visual_have_buffers(visual, 1 << statt))
373 return;
374
375 switch (statt) {
376 case ST_ATTACHMENT_FRONT_LEFT:
377 buf = GL_FRONT_LEFT;
378 idx = BUFFER_FRONT_LEFT;
379 break;
380 case ST_ATTACHMENT_BACK_LEFT:
381 buf = GL_BACK_LEFT;
382 idx = BUFFER_BACK_LEFT;
383 break;
384 case ST_ATTACHMENT_FRONT_RIGHT:
385 buf = GL_FRONT_RIGHT;
386 idx = BUFFER_FRONT_RIGHT;
387 break;
388 case ST_ATTACHMENT_BACK_RIGHT:
389 buf = GL_BACK_RIGHT;
390 idx = BUFFER_BACK_RIGHT;
391 break;
392 default:
393 buf = GL_NONE;
394 idx = BUFFER_COUNT;
395 break;
396 }
397
398 if (buf != GL_NONE) {
399 if (buffer)
400 *buffer = buf;
401 if (index)
402 *index = idx;
403 }
404 }
405
406 /**
407 * Create a framebuffer from a manager interface.
408 */
409 static struct st_framebuffer *
410 st_framebuffer_create(struct st_framebuffer_iface *stfbi)
411 {
412 struct st_framebuffer *stfb;
413 __GLcontextModes mode;
414 gl_buffer_index idx;
415
416 stfb = CALLOC_STRUCT(st_framebuffer);
417 if (!stfb)
418 return NULL;
419
420 st_visual_to_context_mode(stfbi->visual, &mode);
421 _mesa_initialize_window_framebuffer(&stfb->Base, &mode);
422
423 /* modify the draw/read buffers of the fb */
424 st_visual_to_default_buffer(stfbi->visual, &stfb->Base.ColorDrawBuffer[0],
425 &stfb->Base._ColorDrawBufferIndexes[0]);
426 st_visual_to_default_buffer(stfbi->visual, &stfb->Base.ColorReadBuffer,
427 &stfb->Base._ColorReadBufferIndex);
428
429 stfb->iface = stfbi;
430
431 /* add the color buffer */
432 idx = stfb->Base._ColorDrawBufferIndexes[0];
433 if (!st_framebuffer_add_renderbuffer(stfb, idx)) {
434 FREE(stfb);
435 return NULL;
436 }
437
438 st_framebuffer_add_renderbuffer(stfb, BUFFER_DEPTH);
439 st_framebuffer_add_renderbuffer(stfb, BUFFER_ACCUM);
440
441 st_framebuffer_update_attachments(stfb);
442
443 stfb->Base.Initialized = GL_TRUE;
444
445 return stfb;
446 }
447
448 /**
449 * Reference a framebuffer.
450 */
451 static void
452 st_framebuffer_reference(struct st_framebuffer **ptr,
453 struct st_framebuffer *stfb)
454 {
455 GLframebuffer *fb = &stfb->Base;
456 _mesa_reference_framebuffer((GLframebuffer **) ptr, fb);
457 }
458
459 static void
460 st_context_notify_invalid_framebuffer(struct st_context_iface *stctxi,
461 struct st_framebuffer_iface *stfbi)
462 {
463 struct st_context *st = (struct st_context *) stctxi;
464 struct st_framebuffer *stfb;
465
466 /* either draw or read winsys fb */
467 stfb = (struct st_framebuffer *) st->ctx->WinSysDrawBuffer;
468 if (!stfb || stfb->iface != stfbi)
469 stfb = (struct st_framebuffer *) st->ctx->WinSysReadBuffer;
470 assert(stfb && stfb->iface == stfbi);
471
472 p_atomic_set(&stfb->revalidate, TRUE);
473 }
474
475 static void
476 st_context_flush(struct st_context_iface *stctxi, unsigned flags,
477 struct pipe_fence_handle **fence)
478 {
479 struct st_context *st = (struct st_context *) stctxi;
480 st_flush(st, flags, fence);
481 if (flags & PIPE_FLUSH_RENDER_CACHE)
482 st_manager_flush_frontbuffer(st);
483 }
484
485 static boolean
486 st_context_teximage(struct st_context_iface *stctxi, enum st_texture_type target,
487 int level, enum pipe_format internal_format,
488 struct pipe_texture *tex, boolean mipmap)
489 {
490 struct st_context *st = (struct st_context *) stctxi;
491 GLcontext *ctx = st->ctx;
492 struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx);
493 struct gl_texture_object *texObj;
494 struct gl_texture_image *texImage;
495 struct st_texture_object *stObj;
496 struct st_texture_image *stImage;
497 GLenum internalFormat;
498
499 switch (target) {
500 case ST_TEXTURE_1D:
501 target = GL_TEXTURE_1D;
502 break;
503 case ST_TEXTURE_2D:
504 target = GL_TEXTURE_2D;
505 break;
506 case ST_TEXTURE_3D:
507 target = GL_TEXTURE_3D;
508 break;
509 case ST_TEXTURE_RECT:
510 target = GL_TEXTURE_RECTANGLE_ARB;
511 break;
512 default:
513 return FALSE;
514 break;
515 }
516
517 if (util_format_get_component_bits(internal_format,
518 UTIL_FORMAT_COLORSPACE_RGB, 3) > 0)
519 internalFormat = GL_RGBA;
520 else
521 internalFormat = GL_RGB;
522
523 texObj = _mesa_select_tex_object(ctx, texUnit, target);
524 _mesa_lock_texture(ctx, texObj);
525
526 stObj = st_texture_object(texObj);
527 /* switch to surface based */
528 if (!stObj->surface_based) {
529 _mesa_clear_texture_object(ctx, texObj);
530 stObj->surface_based = GL_TRUE;
531 }
532
533 texImage = _mesa_get_tex_image(ctx, texObj, target, level);
534 stImage = st_texture_image(texImage);
535 if (tex) {
536 _mesa_init_teximage_fields(ctx, target, texImage,
537 tex->width0, tex->height0, 1, 0, internalFormat);
538 texImage->TexFormat = st_ChooseTextureFormat(ctx, internalFormat,
539 GL_RGBA, GL_UNSIGNED_BYTE);
540 _mesa_set_fetch_functions(texImage, 2);
541 }
542 else {
543 _mesa_clear_texture_image(ctx, texImage);
544 }
545
546 pipe_texture_reference(&stImage->pt, tex);
547
548 _mesa_dirty_texobj(ctx, texObj, GL_TRUE);
549 _mesa_unlock_texture(ctx, texObj);
550
551 return TRUE;
552 }
553
554 static void
555 st_context_destroy(struct st_context_iface *stctxi)
556 {
557 struct st_context *st = (struct st_context *) stctxi;
558 st_destroy_context(st);
559 }
560
561 static struct st_context_iface *
562 st_api_create_context(struct st_api *stapi, struct st_manager *smapi,
563 const struct st_visual *visual,
564 struct st_context_iface *shared_stctxi)
565 {
566 struct st_context *shared_ctx = (struct st_context *) shared_stctxi;
567 struct st_context *st;
568 struct pipe_context *pipe;
569 __GLcontextModes mode;
570
571 pipe = smapi->screen->context_create(smapi->screen, NULL);
572 if (!pipe)
573 return NULL;
574
575 st_visual_to_context_mode(visual, &mode);
576 st = st_create_context(pipe, &mode, shared_ctx);
577 if (!st) {
578 pipe->destroy(pipe);
579 return NULL;
580 }
581
582 st->iface.destroy = st_context_destroy;
583
584 st->iface.notify_invalid_framebuffer =
585 st_context_notify_invalid_framebuffer;
586 st->iface.flush = st_context_flush;
587
588 st->iface.teximage = st_context_teximage;
589 st->iface.copy = NULL;
590
591 st->iface.st_context_private = (void *) smapi;
592
593 return &st->iface;
594 }
595
596 static boolean
597 st_api_make_current(struct st_api *stapi, struct st_context_iface *stctxi,
598 struct st_framebuffer_iface *stdrawi,
599 struct st_framebuffer_iface *streadi)
600 {
601 struct st_context *st = (struct st_context *) stctxi;
602 struct st_framebuffer *stdraw, *stread, *stfb;
603 boolean ret;
604
605 _glapi_check_multithread();
606
607 if (st) {
608 /* reuse/create the draw fb */
609 stfb = (struct st_framebuffer * ) st->ctx->DrawBuffer;
610 if (stfb && stfb->iface == stdrawi) {
611 stdraw = NULL;
612 st_framebuffer_reference(&stdraw, stfb);
613 }
614 else {
615 stdraw = st_framebuffer_create(stdrawi);
616 }
617
618 /* reuse/create the read fb */
619 stfb = (struct st_framebuffer * ) st->ctx->ReadBuffer;
620 if (!stfb || stfb->iface != streadi)
621 stfb = stdraw;
622 if (stfb && stfb->iface == streadi) {
623 stread = NULL;
624 st_framebuffer_reference(&stread, stfb);
625 }
626 else {
627 stread = st_framebuffer_create(streadi);
628 }
629
630 if (stdraw && stread) {
631 st_framebuffer_validate(stdraw, st);
632 if (stread != stdraw)
633 st_framebuffer_validate(stread, st);
634
635 /* modify the draw/read buffers of the context */
636 st_visual_to_default_buffer(stdraw->iface->visual,
637 &st->ctx->Color.DrawBuffer[0], NULL);
638 st_visual_to_default_buffer(stread->iface->visual,
639 &st->ctx->Pixel.ReadBuffer, NULL);
640
641 ret = _mesa_make_current(st->ctx, &stdraw->Base, &stread->Base);
642 }
643 else {
644 ret = FALSE;
645 }
646
647 st_framebuffer_reference(&stdraw, NULL);
648 st_framebuffer_reference(&stread, NULL);
649 }
650 else {
651 ret = _mesa_make_current(NULL, NULL, NULL);
652 }
653
654 return ret;
655 }
656
657 static struct st_context_iface *
658 st_api_get_current(struct st_api *stapi)
659 {
660 GET_CURRENT_CONTEXT(ctx);
661 struct st_context *st = (ctx) ? ctx->st : NULL;
662
663 return (st) ? &st->iface : NULL;
664 }
665
666 static boolean
667 st_api_is_visual_supported(struct st_api *stapi,
668 const struct st_visual *visual)
669 {
670 return TRUE;
671 }
672
673 static st_proc_t
674 st_api_get_proc_address(struct st_api *stapi, const char *procname)
675 {
676 return (st_proc_t) _glapi_get_proc_address(procname);
677 }
678
679 static void
680 st_api_destroy(struct st_api *stapi)
681 {
682 FREE(stapi);
683 }
684
685 /**
686 * Flush the front buffer if the current context renders to the front buffer.
687 */
688 void
689 st_manager_flush_frontbuffer(struct st_context *st)
690 {
691 struct st_framebuffer *stfb = (struct st_framebuffer *) st->ctx->DrawBuffer;
692 struct st_renderbuffer *strb = NULL;
693
694 if (stfb)
695 strb = st_renderbuffer(stfb->Base.Attachment[BUFFER_FRONT_LEFT].Renderbuffer);
696 if (!strb)
697 return;
698
699 /* st_public.h or FBO */
700 if (!stfb->iface) {
701 struct pipe_surface *front_surf = strb->surface;
702 st->pipe->screen->flush_frontbuffer(st->pipe->screen,
703 front_surf, st->winsys_drawable_handle);
704 return;
705 }
706
707 stfb->iface->flush_front(stfb->iface, ST_ATTACHMENT_FRONT_LEFT);
708 }
709
710 /**
711 * Re-validate the framebuffer.
712 */
713 void
714 st_manager_validate_framebuffers(struct st_context *st)
715 {
716 struct st_framebuffer *stdraw, *stread;
717
718 stdraw = (struct st_framebuffer *) st->ctx->DrawBuffer;
719 stread = (struct st_framebuffer *) st->ctx->ReadBuffer;
720
721 /* st_public.h or FBO */
722 if ((stdraw && !stdraw->iface) || (stread && !stread->iface)) {
723 struct pipe_screen *screen = st->pipe->screen;
724 if (screen->update_buffer)
725 screen->update_buffer(screen, st->pipe->priv);
726 return;
727 }
728
729 if (stdraw)
730 st_framebuffer_validate(stdraw, st);
731 if (stread && stread != stdraw)
732 st_framebuffer_validate(stread, st);
733 }
734
735 /**
736 * Add a color buffer on demand.
737 */
738 boolean
739 st_manager_add_color_renderbuffer(struct st_context *st, GLframebuffer *fb,
740 gl_buffer_index idx)
741 {
742 struct st_framebuffer *stfb = (struct st_framebuffer *) fb;
743
744 if (stfb->Base.Attachment[idx].Renderbuffer)
745 return TRUE;
746
747 /* st_public.h or FBO */
748 if (!stfb->iface)
749 return FALSE;
750
751 switch (idx) {
752 case BUFFER_FRONT_LEFT:
753 case BUFFER_BACK_LEFT:
754 case BUFFER_FRONT_RIGHT:
755 case BUFFER_BACK_RIGHT:
756 break;
757 default:
758 return FALSE;
759 break;
760 }
761
762 if (!st_framebuffer_add_renderbuffer(stfb, idx))
763 return FALSE;
764
765 st_framebuffer_update_attachments(stfb);
766 st_invalidate_state(st->ctx, _NEW_BUFFERS);
767
768 return TRUE;
769 }
770
771 struct st_api *
772 st_manager_create_api(void)
773 {
774 struct st_api *stapi;
775
776 stapi = CALLOC_STRUCT(st_api);
777 if (stapi) {
778 stapi->destroy = st_api_destroy;
779 stapi->get_proc_address = st_api_get_proc_address;
780 stapi->is_visual_supported = st_api_is_visual_supported;
781
782 stapi->create_context = st_api_create_context;
783 stapi->make_current = st_api_make_current;
784 stapi->get_current = st_api_get_current;
785 }
786
787 return stapi;
788 }