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