st/mesa: remove redundant flushes from st_flush
[mesa.git] / src / mesa / state_tracker / st_manager.c
1 /*
2 * Mesa 3-D graphics library
3 *
4 * Copyright (C) 2010 LunarG Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 *
24 * Authors:
25 * Chia-I Wu <olv@lunarg.com>
26 */
27
28 #include "main/mtypes.h"
29 #include "main/extensions.h"
30 #include "main/context.h"
31 #include "main/debug_output.h"
32 #include "main/glthread.h"
33 #include "main/texobj.h"
34 #include "main/teximage.h"
35 #include "main/texstate.h"
36 #include "main/errors.h"
37 #include "main/framebuffer.h"
38 #include "main/fbobject.h"
39 #include "main/renderbuffer.h"
40 #include "main/version.h"
41 #include "util/hash_table.h"
42 #include "st_texture.h"
43
44 #include "st_context.h"
45 #include "st_debug.h"
46 #include "st_extensions.h"
47 #include "st_format.h"
48 #include "st_cb_bitmap.h"
49 #include "st_cb_fbo.h"
50 #include "st_cb_flush.h"
51 #include "st_manager.h"
52 #include "st_sampler_view.h"
53
54 #include "state_tracker/st_gl_api.h"
55
56 #include "pipe/p_context.h"
57 #include "pipe/p_screen.h"
58 #include "util/u_format.h"
59 #include "util/u_pointer.h"
60 #include "util/u_inlines.h"
61 #include "util/u_atomic.h"
62 #include "util/u_surface.h"
63 #include "util/list.h"
64
65 struct hash_table;
66 struct st_manager_private
67 {
68 struct hash_table *stfbi_ht; /* framebuffer iface objects hash table */
69 mtx_t st_mutex;
70 };
71
72 static void st_manager_destroy(struct st_manager *);
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 * Make sure a context picks up the latest cached state of the
147 * drawables it binds to.
148 */
149 static void
150 st_context_validate(struct st_context *st,
151 struct st_framebuffer *stdraw,
152 struct st_framebuffer *stread)
153 {
154 if (stdraw && stdraw->stamp != st->draw_stamp) {
155 st->dirty |= ST_NEW_FRAMEBUFFER;
156 _mesa_resize_framebuffer(st->ctx, &stdraw->Base,
157 stdraw->Base.Width,
158 stdraw->Base.Height);
159 st->draw_stamp = stdraw->stamp;
160 }
161
162 if (stread && stread->stamp != st->read_stamp) {
163 if (stread != stdraw) {
164 st->dirty |= ST_NEW_FRAMEBUFFER;
165 _mesa_resize_framebuffer(st->ctx, &stread->Base,
166 stread->Base.Width,
167 stread->Base.Height);
168 }
169 st->read_stamp = stread->stamp;
170 }
171 }
172
173 /**
174 * Validate a framebuffer to make sure up-to-date pipe_textures are used.
175 * The context is only used for creating pipe surfaces and for calling
176 * _mesa_resize_framebuffer().
177 * (That should probably be rethought, since those surfaces become
178 * drawable state, not context state, and can be freed by another pipe
179 * context).
180 */
181 static void
182 st_framebuffer_validate(struct st_framebuffer *stfb,
183 struct st_context *st)
184 {
185 struct pipe_resource *textures[ST_ATTACHMENT_COUNT];
186 uint width, height;
187 unsigned i;
188 boolean changed = FALSE;
189 int32_t new_stamp;
190
191 new_stamp = p_atomic_read(&stfb->iface->stamp);
192 if (stfb->iface_stamp == new_stamp)
193 return;
194
195 memset(textures, 0, stfb->num_statts * sizeof(textures[0]));
196
197 /* validate the fb */
198 do {
199 if (!stfb->iface->validate(&st->iface, stfb->iface, stfb->statts,
200 stfb->num_statts, textures))
201 return;
202
203 stfb->iface_stamp = new_stamp;
204 new_stamp = p_atomic_read(&stfb->iface->stamp);
205 } while(stfb->iface_stamp != new_stamp);
206
207 width = stfb->Base.Width;
208 height = stfb->Base.Height;
209
210 for (i = 0; i < stfb->num_statts; i++) {
211 struct st_renderbuffer *strb;
212 struct pipe_surface *ps, surf_tmpl;
213 gl_buffer_index idx;
214
215 if (!textures[i])
216 continue;
217
218 idx = attachment_to_buffer_index(stfb->statts[i]);
219 if (idx >= BUFFER_COUNT) {
220 pipe_resource_reference(&textures[i], NULL);
221 continue;
222 }
223
224 strb = st_renderbuffer(stfb->Base.Attachment[idx].Renderbuffer);
225 assert(strb);
226 if (strb->texture == textures[i]) {
227 pipe_resource_reference(&textures[i], NULL);
228 continue;
229 }
230
231 u_surface_default_template(&surf_tmpl, textures[i]);
232 ps = st->pipe->create_surface(st->pipe, textures[i], &surf_tmpl);
233 if (ps) {
234 struct pipe_surface **psurf =
235 util_format_is_srgb(ps->format) ? &strb->surface_srgb :
236 &strb->surface_linear;
237
238 pipe_surface_reference(psurf, ps);
239 strb->surface = *psurf;
240 pipe_resource_reference(&strb->texture, ps->texture);
241 /* ownership transfered */
242 pipe_surface_reference(&ps, NULL);
243
244 changed = TRUE;
245
246 strb->Base.Width = strb->surface->width;
247 strb->Base.Height = strb->surface->height;
248
249 width = strb->Base.Width;
250 height = strb->Base.Height;
251 }
252
253 pipe_resource_reference(&textures[i], NULL);
254 }
255
256 if (changed) {
257 ++stfb->stamp;
258 _mesa_resize_framebuffer(st->ctx, &stfb->Base, width, height);
259 }
260 }
261
262 /**
263 * Update the attachments to validate by looping the existing renderbuffers.
264 */
265 static void
266 st_framebuffer_update_attachments(struct st_framebuffer *stfb)
267 {
268 gl_buffer_index idx;
269
270 stfb->num_statts = 0;
271 for (idx = 0; idx < BUFFER_COUNT; idx++) {
272 struct st_renderbuffer *strb;
273 enum st_attachment_type statt;
274
275 strb = st_renderbuffer(stfb->Base.Attachment[idx].Renderbuffer);
276 if (!strb || strb->software)
277 continue;
278
279 statt = buffer_index_to_attachment(idx);
280 if (statt != ST_ATTACHMENT_INVALID &&
281 st_visual_have_buffers(stfb->iface->visual, 1 << statt))
282 stfb->statts[stfb->num_statts++] = statt;
283 }
284 stfb->stamp++;
285 }
286
287 /**
288 * Add a renderbuffer to the framebuffer. The framebuffer is one that
289 * corresponds to a window and is not a user-created FBO.
290 */
291 static boolean
292 st_framebuffer_add_renderbuffer(struct st_framebuffer *stfb,
293 gl_buffer_index idx)
294 {
295 struct gl_renderbuffer *rb;
296 enum pipe_format format;
297 boolean sw;
298
299 assert(_mesa_is_winsys_fbo(&stfb->Base));
300
301 /* do not distinguish depth/stencil buffers */
302 if (idx == BUFFER_STENCIL)
303 idx = BUFFER_DEPTH;
304
305 switch (idx) {
306 case BUFFER_DEPTH:
307 format = stfb->iface->visual->depth_stencil_format;
308 sw = FALSE;
309 break;
310 case BUFFER_ACCUM:
311 format = stfb->iface->visual->accum_format;
312 sw = TRUE;
313 break;
314 default:
315 format = stfb->iface->visual->color_format;
316 if (stfb->Base.Visual.sRGBCapable)
317 format = util_format_srgb(format);
318 sw = FALSE;
319 break;
320 }
321
322 if (format == PIPE_FORMAT_NONE)
323 return FALSE;
324
325 rb = st_new_renderbuffer_fb(format, stfb->iface->visual->samples, sw);
326 if (!rb)
327 return FALSE;
328
329 if (idx != BUFFER_DEPTH) {
330 _mesa_attach_and_own_rb(&stfb->Base, idx, rb);
331 return TRUE;
332 }
333
334 bool rb_ownership_taken = false;
335 if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_ZS, 0)) {
336 _mesa_attach_and_own_rb(&stfb->Base, BUFFER_DEPTH, rb);
337 rb_ownership_taken = true;
338 }
339
340 if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_ZS, 1)) {
341 if (rb_ownership_taken)
342 _mesa_attach_and_reference_rb(&stfb->Base, BUFFER_STENCIL, rb);
343 else
344 _mesa_attach_and_own_rb(&stfb->Base, BUFFER_STENCIL, rb);
345 }
346
347 return TRUE;
348 }
349
350 /**
351 * Intialize a struct gl_config from a visual.
352 */
353 static void
354 st_visual_to_context_mode(const struct st_visual *visual,
355 struct gl_config *mode)
356 {
357 memset(mode, 0, sizeof(*mode));
358
359 if (st_visual_have_buffers(visual, ST_ATTACHMENT_BACK_LEFT_MASK))
360 mode->doubleBufferMode = GL_TRUE;
361 if (st_visual_have_buffers(visual,
362 ST_ATTACHMENT_FRONT_RIGHT_MASK | ST_ATTACHMENT_BACK_RIGHT_MASK))
363 mode->stereoMode = GL_TRUE;
364
365 if (visual->color_format != PIPE_FORMAT_NONE) {
366 mode->rgbMode = GL_TRUE;
367
368 mode->redBits =
369 util_format_get_component_bits(visual->color_format,
370 UTIL_FORMAT_COLORSPACE_RGB, 0);
371 mode->greenBits =
372 util_format_get_component_bits(visual->color_format,
373 UTIL_FORMAT_COLORSPACE_RGB, 1);
374 mode->blueBits =
375 util_format_get_component_bits(visual->color_format,
376 UTIL_FORMAT_COLORSPACE_RGB, 2);
377 mode->alphaBits =
378 util_format_get_component_bits(visual->color_format,
379 UTIL_FORMAT_COLORSPACE_RGB, 3);
380
381 mode->rgbBits = mode->redBits +
382 mode->greenBits + mode->blueBits + mode->alphaBits;
383 mode->sRGBCapable = util_format_is_srgb(visual->color_format);
384 }
385
386 if (visual->depth_stencil_format != PIPE_FORMAT_NONE) {
387 mode->depthBits =
388 util_format_get_component_bits(visual->depth_stencil_format,
389 UTIL_FORMAT_COLORSPACE_ZS, 0);
390 mode->stencilBits =
391 util_format_get_component_bits(visual->depth_stencil_format,
392 UTIL_FORMAT_COLORSPACE_ZS, 1);
393
394 mode->haveDepthBuffer = mode->depthBits > 0;
395 mode->haveStencilBuffer = mode->stencilBits > 0;
396 }
397
398 if (visual->accum_format != PIPE_FORMAT_NONE) {
399 mode->haveAccumBuffer = GL_TRUE;
400
401 mode->accumRedBits =
402 util_format_get_component_bits(visual->accum_format,
403 UTIL_FORMAT_COLORSPACE_RGB, 0);
404 mode->accumGreenBits =
405 util_format_get_component_bits(visual->accum_format,
406 UTIL_FORMAT_COLORSPACE_RGB, 1);
407 mode->accumBlueBits =
408 util_format_get_component_bits(visual->accum_format,
409 UTIL_FORMAT_COLORSPACE_RGB, 2);
410 mode->accumAlphaBits =
411 util_format_get_component_bits(visual->accum_format,
412 UTIL_FORMAT_COLORSPACE_RGB, 3);
413 }
414
415 if (visual->samples > 1) {
416 mode->sampleBuffers = 1;
417 mode->samples = visual->samples;
418 }
419 }
420
421 /**
422 * Create a framebuffer from a manager interface.
423 */
424 static struct st_framebuffer *
425 st_framebuffer_create(struct st_context *st,
426 struct st_framebuffer_iface *stfbi)
427 {
428 struct st_framebuffer *stfb;
429 struct gl_config mode;
430 gl_buffer_index idx;
431
432 if (!stfbi)
433 return NULL;
434
435 stfb = CALLOC_STRUCT(st_framebuffer);
436 if (!stfb)
437 return NULL;
438
439 st_visual_to_context_mode(stfbi->visual, &mode);
440
441 /*
442 * For desktop GL, sRGB framebuffer write is controlled by both the
443 * capability of the framebuffer and GL_FRAMEBUFFER_SRGB. We should
444 * advertise the capability when the pipe driver (and core Mesa) supports
445 * it so that applications can enable sRGB write when they want to.
446 *
447 * This is not to be confused with GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB. When
448 * the attribute is GLX_TRUE, it tells the st manager to pick a color
449 * format such that util_format_srgb(visual->color_format) can be supported
450 * by the pipe driver. We still need to advertise the capability here.
451 *
452 * For GLES, however, sRGB framebuffer write is controlled only by the
453 * capability of the framebuffer. There is GL_EXT_sRGB_write_control to
454 * give applications the control back, but sRGB write is still enabled by
455 * default. To avoid unexpected results, we should not advertise the
456 * capability. This could change when we add support for
457 * EGL_KHR_gl_colorspace.
458 */
459 if (_mesa_is_desktop_gl(st->ctx)) {
460 struct pipe_screen *screen = st->pipe->screen;
461 const enum pipe_format srgb_format =
462 util_format_srgb(stfbi->visual->color_format);
463
464 if (srgb_format != PIPE_FORMAT_NONE &&
465 st_pipe_format_to_mesa_format(srgb_format) != MESA_FORMAT_NONE &&
466 screen->is_format_supported(screen, srgb_format,
467 PIPE_TEXTURE_2D, stfbi->visual->samples,
468 (PIPE_BIND_DISPLAY_TARGET |
469 PIPE_BIND_RENDER_TARGET)))
470 mode.sRGBCapable = GL_TRUE;
471 }
472
473 _mesa_initialize_window_framebuffer(&stfb->Base, &mode);
474
475 stfb->iface = stfbi;
476 stfb->iface_ID = stfbi->ID;
477 stfb->iface_stamp = p_atomic_read(&stfbi->stamp) - 1;
478
479 /* add the color buffer */
480 idx = stfb->Base._ColorDrawBufferIndexes[0];
481 if (!st_framebuffer_add_renderbuffer(stfb, idx)) {
482 free(stfb);
483 return NULL;
484 }
485
486 st_framebuffer_add_renderbuffer(stfb, BUFFER_DEPTH);
487 st_framebuffer_add_renderbuffer(stfb, BUFFER_ACCUM);
488
489 stfb->stamp = 0;
490 st_framebuffer_update_attachments(stfb);
491
492 return stfb;
493 }
494
495 /**
496 * Reference a framebuffer.
497 */
498 void
499 st_framebuffer_reference(struct st_framebuffer **ptr,
500 struct st_framebuffer *stfb)
501 {
502 struct gl_framebuffer *fb = &stfb->Base;
503 _mesa_reference_framebuffer((struct gl_framebuffer **) ptr, fb);
504 }
505
506
507 static uint32_t
508 st_framebuffer_iface_hash(const void *key)
509 {
510 return (uintptr_t)key;
511 }
512
513
514 static bool
515 st_framebuffer_iface_equal(const void *a, const void *b)
516 {
517 return (struct st_framebuffer_iface *)a == (struct st_framebuffer_iface *)b;
518 }
519
520
521 static boolean
522 st_framebuffer_iface_lookup(struct st_manager *smapi,
523 const struct st_framebuffer_iface *stfbi)
524 {
525 struct st_manager_private *smPriv =
526 (struct st_manager_private *)smapi->st_manager_private;
527 struct hash_entry *entry;
528
529 assert(smPriv);
530 assert(smPriv->stfbi_ht);
531
532 mtx_lock(&smPriv->st_mutex);
533 entry = _mesa_hash_table_search(smPriv->stfbi_ht, stfbi);
534 mtx_unlock(&smPriv->st_mutex);
535
536 return entry != NULL;
537 }
538
539
540 static boolean
541 st_framebuffer_iface_insert(struct st_manager *smapi,
542 struct st_framebuffer_iface *stfbi)
543 {
544 struct st_manager_private *smPriv =
545 (struct st_manager_private *)smapi->st_manager_private;
546 struct hash_entry *entry;
547
548 assert(smPriv);
549 assert(smPriv->stfbi_ht);
550
551 mtx_lock(&smPriv->st_mutex);
552 entry = _mesa_hash_table_insert(smPriv->stfbi_ht, stfbi, stfbi);
553 mtx_unlock(&smPriv->st_mutex);
554
555 return entry != NULL;
556 }
557
558
559 static void
560 st_framebuffer_iface_remove(struct st_manager *smapi,
561 struct st_framebuffer_iface *stfbi)
562 {
563 struct st_manager_private *smPriv =
564 (struct st_manager_private *)smapi->st_manager_private;
565 struct hash_entry *entry;
566
567 if (!smPriv || !smPriv->stfbi_ht)
568 return;
569
570 mtx_lock(&smPriv->st_mutex);
571 entry = _mesa_hash_table_search(smPriv->stfbi_ht, stfbi);
572 if (!entry)
573 goto unlock;
574
575 _mesa_hash_table_remove(smPriv->stfbi_ht, entry);
576
577 unlock:
578 mtx_unlock(&smPriv->st_mutex);
579 }
580
581
582 /**
583 * The framebuffer interface object is no longer valid.
584 * Remove the object from the framebuffer interface hash table.
585 */
586 static void
587 st_api_destroy_drawable(struct st_api *stapi,
588 struct st_framebuffer_iface *stfbi)
589 {
590 if (!stfbi)
591 return;
592
593 st_framebuffer_iface_remove(stfbi->state_manager, stfbi);
594 }
595
596
597 /**
598 * Purge the winsys buffers list to remove any references to
599 * non-existing framebuffer interface objects.
600 */
601 static void
602 st_framebuffers_purge(struct st_context *st)
603 {
604 struct st_context_iface *st_iface = &st->iface;
605 struct st_manager *smapi = st_iface->state_manager;
606 struct st_framebuffer *stfb, *next;
607
608 assert(smapi);
609
610 LIST_FOR_EACH_ENTRY_SAFE_REV(stfb, next, &st->winsys_buffers, head) {
611 struct st_framebuffer_iface *stfbi = stfb->iface;
612
613 assert(stfbi);
614
615 /**
616 * If the corresponding framebuffer interface object no longer exists,
617 * remove the framebuffer object from the context's winsys buffers list,
618 * and unreference the framebuffer object, so its resources can be
619 * deleted.
620 */
621 if (!st_framebuffer_iface_lookup(smapi, stfbi)) {
622 LIST_DEL(&stfb->head);
623 st_framebuffer_reference(&stfb, NULL);
624 }
625 }
626 }
627
628 static void
629 st_context_flush(struct st_context_iface *stctxi, unsigned flags,
630 struct pipe_fence_handle **fence)
631 {
632 struct st_context *st = (struct st_context *) stctxi;
633 unsigned pipe_flags = 0;
634
635 if (flags & ST_FLUSH_END_OF_FRAME) {
636 pipe_flags |= PIPE_FLUSH_END_OF_FRAME;
637 }
638
639 FLUSH_VERTICES(st->ctx, 0);
640 FLUSH_CURRENT(st->ctx, 0);
641 st_flush(st, fence, pipe_flags);
642
643 if ((flags & ST_FLUSH_WAIT) && fence && *fence) {
644 st->pipe->screen->fence_finish(st->pipe->screen, NULL, *fence,
645 PIPE_TIMEOUT_INFINITE);
646 st->pipe->screen->fence_reference(st->pipe->screen, fence, NULL);
647 }
648
649 if (flags & ST_FLUSH_FRONT)
650 st_manager_flush_frontbuffer(st);
651
652 /* DRI3 changes the framebuffer after SwapBuffers, but we need to invoke
653 * st_manager_validate_framebuffers to notice that.
654 *
655 * Set gfx_shaders_may_be_dirty to invoke st_validate_state in the next
656 * draw call, which will invoke st_manager_validate_framebuffers, but it
657 * won't dirty states if there is no change.
658 */
659 if (flags & ST_FLUSH_END_OF_FRAME)
660 st->gfx_shaders_may_be_dirty = true;
661 }
662
663 static boolean
664 st_context_teximage(struct st_context_iface *stctxi,
665 enum st_texture_type tex_type,
666 int level, enum pipe_format pipe_format,
667 struct pipe_resource *tex, boolean mipmap)
668 {
669 struct st_context *st = (struct st_context *) stctxi;
670 struct gl_context *ctx = st->ctx;
671 struct gl_texture_object *texObj;
672 struct gl_texture_image *texImage;
673 struct st_texture_object *stObj;
674 struct st_texture_image *stImage;
675 GLenum internalFormat;
676 GLuint width, height, depth;
677 GLenum target;
678
679 switch (tex_type) {
680 case ST_TEXTURE_1D:
681 target = GL_TEXTURE_1D;
682 break;
683 case ST_TEXTURE_2D:
684 target = GL_TEXTURE_2D;
685 break;
686 case ST_TEXTURE_3D:
687 target = GL_TEXTURE_3D;
688 break;
689 case ST_TEXTURE_RECT:
690 target = GL_TEXTURE_RECTANGLE_ARB;
691 break;
692 default:
693 return FALSE;
694 }
695
696 texObj = _mesa_get_current_tex_object(ctx, target);
697
698 _mesa_lock_texture(ctx, texObj);
699
700 stObj = st_texture_object(texObj);
701 /* switch to surface based */
702 if (!stObj->surface_based) {
703 _mesa_clear_texture_object(ctx, texObj, NULL);
704 stObj->surface_based = GL_TRUE;
705 }
706
707 texImage = _mesa_get_tex_image(ctx, texObj, target, level);
708 stImage = st_texture_image(texImage);
709 if (tex) {
710 mesa_format texFormat = st_pipe_format_to_mesa_format(pipe_format);
711
712 if (util_format_has_alpha(tex->format))
713 internalFormat = GL_RGBA;
714 else
715 internalFormat = GL_RGB;
716
717 _mesa_init_teximage_fields(ctx, texImage,
718 tex->width0, tex->height0, 1, 0,
719 internalFormat, texFormat);
720
721 width = tex->width0;
722 height = tex->height0;
723 depth = tex->depth0;
724
725 /* grow the image size until we hit level = 0 */
726 while (level > 0) {
727 if (width != 1)
728 width <<= 1;
729 if (height != 1)
730 height <<= 1;
731 if (depth != 1)
732 depth <<= 1;
733 level--;
734 }
735 }
736 else {
737 _mesa_clear_texture_image(ctx, texImage);
738 width = height = depth = 0;
739 }
740
741 pipe_resource_reference(&stObj->pt, tex);
742 st_texture_release_all_sampler_views(st, stObj);
743 pipe_resource_reference(&stImage->pt, tex);
744 stObj->surface_format = pipe_format;
745
746 stObj->needs_validation = true;
747
748 _mesa_dirty_texobj(ctx, texObj);
749 _mesa_unlock_texture(ctx, texObj);
750
751 return TRUE;
752 }
753
754 static void
755 st_context_copy(struct st_context_iface *stctxi,
756 struct st_context_iface *stsrci, unsigned mask)
757 {
758 struct st_context *st = (struct st_context *) stctxi;
759 struct st_context *src = (struct st_context *) stsrci;
760
761 _mesa_copy_context(src->ctx, st->ctx, mask);
762 }
763
764 static boolean
765 st_context_share(struct st_context_iface *stctxi,
766 struct st_context_iface *stsrci)
767 {
768 struct st_context *st = (struct st_context *) stctxi;
769 struct st_context *src = (struct st_context *) stsrci;
770
771 return _mesa_share_state(st->ctx, src->ctx);
772 }
773
774 static void
775 st_context_destroy(struct st_context_iface *stctxi)
776 {
777 struct st_context *st = (struct st_context *) stctxi;
778 st_destroy_context(st);
779 }
780
781 static void
782 st_start_thread(struct st_context_iface *stctxi)
783 {
784 struct st_context *st = (struct st_context *) stctxi;
785
786 _mesa_glthread_init(st->ctx);
787 }
788
789 static void
790 st_thread_finish(struct st_context_iface *stctxi)
791 {
792 struct st_context *st = (struct st_context *) stctxi;
793
794 _mesa_glthread_finish(st->ctx);
795 }
796
797 static struct st_context_iface *
798 st_api_create_context(struct st_api *stapi, struct st_manager *smapi,
799 const struct st_context_attribs *attribs,
800 enum st_context_error *error,
801 struct st_context_iface *shared_stctxi)
802 {
803 struct st_context *shared_ctx = (struct st_context *) shared_stctxi;
804 struct st_context *st;
805 struct pipe_context *pipe;
806 struct gl_config mode;
807 gl_api api;
808 bool no_error = false;
809 unsigned ctx_flags = PIPE_CONTEXT_PREFER_THREADED;
810
811 if (!(stapi->profile_mask & (1 << attribs->profile)))
812 return NULL;
813
814 switch (attribs->profile) {
815 case ST_PROFILE_DEFAULT:
816 api = API_OPENGL_COMPAT;
817 break;
818 case ST_PROFILE_OPENGL_ES1:
819 api = API_OPENGLES;
820 break;
821 case ST_PROFILE_OPENGL_ES2:
822 api = API_OPENGLES2;
823 break;
824 case ST_PROFILE_OPENGL_CORE:
825 api = API_OPENGL_CORE;
826 break;
827 default:
828 *error = ST_CONTEXT_ERROR_BAD_API;
829 return NULL;
830 }
831
832 /* Create a hash table for the framebuffer interface objects
833 * if it has not been created for this st manager.
834 */
835 if (smapi->st_manager_private == NULL) {
836 struct st_manager_private *smPriv;
837
838 smPriv = CALLOC_STRUCT(st_manager_private);
839 mtx_init(&smPriv->st_mutex, mtx_plain);
840 smPriv->stfbi_ht = _mesa_hash_table_create(NULL,
841 st_framebuffer_iface_hash,
842 st_framebuffer_iface_equal);
843 smapi->st_manager_private = smPriv;
844 smapi->destroy = st_manager_destroy;
845 }
846
847 if (attribs->flags & ST_CONTEXT_FLAG_ROBUST_ACCESS)
848 ctx_flags |= PIPE_CONTEXT_ROBUST_BUFFER_ACCESS;
849
850 if (attribs->flags & ST_CONTEXT_FLAG_NO_ERROR)
851 no_error = true;
852
853 pipe = smapi->screen->context_create(smapi->screen, NULL, ctx_flags);
854 if (!pipe) {
855 *error = ST_CONTEXT_ERROR_NO_MEMORY;
856 return NULL;
857 }
858
859 st_visual_to_context_mode(&attribs->visual, &mode);
860 st = st_create_context(api, pipe, &mode, shared_ctx, &attribs->options, no_error);
861 if (!st) {
862 *error = ST_CONTEXT_ERROR_NO_MEMORY;
863 pipe->destroy(pipe);
864 return NULL;
865 }
866
867 if (attribs->flags & ST_CONTEXT_FLAG_DEBUG) {
868 if (!_mesa_set_debug_state_int(st->ctx, GL_DEBUG_OUTPUT, GL_TRUE)) {
869 *error = ST_CONTEXT_ERROR_NO_MEMORY;
870 return NULL;
871 }
872
873 st->ctx->Const.ContextFlags |= GL_CONTEXT_FLAG_DEBUG_BIT;
874 }
875
876 if (st->ctx->Const.ContextFlags & GL_CONTEXT_FLAG_DEBUG_BIT) {
877 st_update_debug_callback(st);
878 }
879
880 if (attribs->flags & ST_CONTEXT_FLAG_FORWARD_COMPATIBLE)
881 st->ctx->Const.ContextFlags |= GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT;
882 if (attribs->flags & ST_CONTEXT_FLAG_ROBUST_ACCESS) {
883 st->ctx->Const.ContextFlags |= GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT_ARB;
884 st->ctx->Const.RobustAccess = GL_TRUE;
885 }
886 if (attribs->flags & ST_CONTEXT_FLAG_RESET_NOTIFICATION_ENABLED) {
887 st->ctx->Const.ResetStrategy = GL_LOSE_CONTEXT_ON_RESET_ARB;
888 st_install_device_reset_callback(st);
889 }
890
891 if (attribs->flags & ST_CONTEXT_FLAG_RELEASE_NONE)
892 st->ctx->Const.ContextReleaseBehavior = GL_NONE;
893
894 /* need to perform version check */
895 if (attribs->major > 1 || attribs->minor > 0) {
896 /* Is the actual version less than the requested version?
897 */
898 if (st->ctx->Version < attribs->major * 10U + attribs->minor) {
899 *error = ST_CONTEXT_ERROR_BAD_VERSION;
900 st_destroy_context(st);
901 return NULL;
902 }
903 }
904
905 st->invalidate_on_gl_viewport =
906 smapi->get_param(smapi, ST_MANAGER_BROKEN_INVALIDATE);
907
908 st->iface.destroy = st_context_destroy;
909 st->iface.flush = st_context_flush;
910 st->iface.teximage = st_context_teximage;
911 st->iface.copy = st_context_copy;
912 st->iface.share = st_context_share;
913 st->iface.start_thread = st_start_thread;
914 st->iface.thread_finish = st_thread_finish;
915 st->iface.st_context_private = (void *) smapi;
916 st->iface.cso_context = st->cso_context;
917 st->iface.pipe = st->pipe;
918 st->iface.state_manager = smapi;
919
920 *error = ST_CONTEXT_SUCCESS;
921 return &st->iface;
922 }
923
924 static struct st_context_iface *
925 st_api_get_current(struct st_api *stapi)
926 {
927 GET_CURRENT_CONTEXT(ctx);
928 struct st_context *st = (ctx) ? ctx->st : NULL;
929
930 return (st) ? &st->iface : NULL;
931 }
932
933 static struct st_framebuffer *
934 st_framebuffer_reuse_or_create(struct st_context *st,
935 struct gl_framebuffer *fb,
936 struct st_framebuffer_iface *stfbi)
937 {
938 struct st_framebuffer *cur = NULL, *stfb = NULL;
939
940 if (!stfbi)
941 return NULL;
942
943 /* Check if there is already a framebuffer object for the specified
944 * framebuffer interface in this context. If there is one, use it.
945 */
946 LIST_FOR_EACH_ENTRY(cur, &st->winsys_buffers, head) {
947 if (cur->iface_ID == stfbi->ID) {
948 st_framebuffer_reference(&stfb, cur);
949 break;
950 }
951 }
952
953 /* If there is not already a framebuffer object, create one */
954 if (stfb == NULL) {
955 cur = st_framebuffer_create(st, stfbi);
956
957 if (cur) {
958 /* add the referenced framebuffer interface object to
959 * the framebuffer interface object hash table.
960 */
961 if (!st_framebuffer_iface_insert(stfbi->state_manager, stfbi)) {
962 st_framebuffer_reference(&cur, NULL);
963 return NULL;
964 }
965
966 /* add to the context's winsys buffers list */
967 LIST_ADD(&cur->head, &st->winsys_buffers);
968
969 st_framebuffer_reference(&stfb, cur);
970 }
971 }
972
973 return stfb;
974 }
975
976 static boolean
977 st_api_make_current(struct st_api *stapi, struct st_context_iface *stctxi,
978 struct st_framebuffer_iface *stdrawi,
979 struct st_framebuffer_iface *streadi)
980 {
981 struct st_context *st = (struct st_context *) stctxi;
982 struct st_framebuffer *stdraw, *stread;
983 boolean ret;
984
985 _glapi_check_multithread();
986
987 if (st) {
988 /* reuse or create the draw fb */
989 stdraw = st_framebuffer_reuse_or_create(st,
990 st->ctx->WinSysDrawBuffer, stdrawi);
991 if (streadi != stdrawi) {
992 /* do the same for the read fb */
993 stread = st_framebuffer_reuse_or_create(st,
994 st->ctx->WinSysReadBuffer, streadi);
995 }
996 else {
997 stread = NULL;
998 /* reuse the draw fb for the read fb */
999 if (stdraw)
1000 st_framebuffer_reference(&stread, stdraw);
1001 }
1002
1003 if (stdraw && stread) {
1004 st_framebuffer_validate(stdraw, st);
1005 if (stread != stdraw)
1006 st_framebuffer_validate(stread, st);
1007
1008 ret = _mesa_make_current(st->ctx, &stdraw->Base, &stread->Base);
1009
1010 st->draw_stamp = stdraw->stamp - 1;
1011 st->read_stamp = stread->stamp - 1;
1012 st_context_validate(st, stdraw, stread);
1013 }
1014 else {
1015 struct gl_framebuffer *incomplete = _mesa_get_incomplete_framebuffer();
1016 ret = _mesa_make_current(st->ctx, incomplete, incomplete);
1017 }
1018
1019 st_framebuffer_reference(&stdraw, NULL);
1020 st_framebuffer_reference(&stread, NULL);
1021
1022 /* Purge the context's winsys_buffers list in case any
1023 * of the referenced drawables no longer exist.
1024 */
1025 st_framebuffers_purge(st);
1026 }
1027 else {
1028 ret = _mesa_make_current(NULL, NULL, NULL);
1029 }
1030
1031 return ret;
1032 }
1033
1034 static void
1035 st_api_destroy(struct st_api *stapi)
1036 {
1037 }
1038
1039 /**
1040 * Flush the front buffer if the current context renders to the front buffer.
1041 */
1042 void
1043 st_manager_flush_frontbuffer(struct st_context *st)
1044 {
1045 struct st_framebuffer *stfb = st_ws_framebuffer(st->ctx->DrawBuffer);
1046 struct st_renderbuffer *strb = NULL;
1047
1048 if (stfb)
1049 strb = st_renderbuffer(stfb->Base.Attachment[BUFFER_FRONT_LEFT].Renderbuffer);
1050
1051 /* Do we have a front color buffer and has it been drawn to since last
1052 * frontbuffer flush?
1053 */
1054 if (strb && strb->defined) {
1055 stfb->iface->flush_front(&st->iface, stfb->iface,
1056 ST_ATTACHMENT_FRONT_LEFT);
1057 strb->defined = GL_FALSE;
1058
1059 /* Trigger an update of strb->defined on next draw */
1060 st->dirty |= ST_NEW_FB_STATE;
1061 }
1062 }
1063
1064 /**
1065 * Re-validate the framebuffers.
1066 */
1067 void
1068 st_manager_validate_framebuffers(struct st_context *st)
1069 {
1070 struct st_framebuffer *stdraw = st_ws_framebuffer(st->ctx->DrawBuffer);
1071 struct st_framebuffer *stread = st_ws_framebuffer(st->ctx->ReadBuffer);
1072
1073 if (stdraw)
1074 st_framebuffer_validate(stdraw, st);
1075 if (stread && stread != stdraw)
1076 st_framebuffer_validate(stread, st);
1077
1078 st_context_validate(st, stdraw, stread);
1079 }
1080
1081
1082 /**
1083 * Flush any outstanding swapbuffers on the current draw framebuffer.
1084 */
1085 void
1086 st_manager_flush_swapbuffers(void)
1087 {
1088 GET_CURRENT_CONTEXT(ctx);
1089 struct st_context *st = (ctx) ? ctx->st : NULL;
1090 struct st_framebuffer *stfb;
1091
1092 if (!st)
1093 return;
1094
1095 stfb = st_ws_framebuffer(ctx->DrawBuffer);
1096 if (!stfb || !stfb->iface->flush_swapbuffers)
1097 return;
1098
1099 stfb->iface->flush_swapbuffers(&st->iface, stfb->iface);
1100 }
1101
1102
1103 /**
1104 * Add a color renderbuffer on demand. The FBO must correspond to a window,
1105 * not a user-created FBO.
1106 */
1107 boolean
1108 st_manager_add_color_renderbuffer(struct st_context *st,
1109 struct gl_framebuffer *fb,
1110 gl_buffer_index idx)
1111 {
1112 struct st_framebuffer *stfb = st_ws_framebuffer(fb);
1113
1114 /* FBO */
1115 if (!stfb)
1116 return FALSE;
1117
1118 assert(_mesa_is_winsys_fbo(fb));
1119
1120 if (stfb->Base.Attachment[idx].Renderbuffer)
1121 return TRUE;
1122
1123 switch (idx) {
1124 case BUFFER_FRONT_LEFT:
1125 case BUFFER_BACK_LEFT:
1126 case BUFFER_FRONT_RIGHT:
1127 case BUFFER_BACK_RIGHT:
1128 break;
1129 default:
1130 return FALSE;
1131 }
1132
1133 if (!st_framebuffer_add_renderbuffer(stfb, idx))
1134 return FALSE;
1135
1136 st_framebuffer_update_attachments(stfb);
1137
1138 /*
1139 * Force a call to the state tracker manager to validate the
1140 * new renderbuffer. It might be that there is a window system
1141 * renderbuffer available.
1142 */
1143 if (stfb->iface)
1144 stfb->iface_stamp = p_atomic_read(&stfb->iface->stamp) - 1;
1145
1146 st_invalidate_buffers(st);
1147
1148 return TRUE;
1149 }
1150
1151 static void
1152 st_manager_destroy(struct st_manager *smapi)
1153 {
1154 struct st_manager_private *smPriv = smapi->st_manager_private;
1155
1156 if (smPriv && smPriv->stfbi_ht) {
1157 _mesa_hash_table_destroy(smPriv->stfbi_ht, NULL);
1158 mtx_destroy(&smPriv->st_mutex);
1159 free(smPriv);
1160 smapi->st_manager_private = NULL;
1161 }
1162 }
1163
1164 static unsigned
1165 get_version(struct pipe_screen *screen,
1166 struct st_config_options *options, gl_api api)
1167 {
1168 struct gl_constants consts = {0};
1169 struct gl_extensions extensions = {0};
1170 GLuint version;
1171
1172 if (_mesa_override_gl_version_contextless(&consts, &api, &version)) {
1173 return version;
1174 }
1175
1176 _mesa_init_constants(&consts, api);
1177 _mesa_init_extensions(&extensions);
1178
1179 st_init_limits(screen, &consts, &extensions);
1180 st_init_extensions(screen, &consts, &extensions, options);
1181
1182 return _mesa_get_version(&extensions, &consts, api);
1183 }
1184
1185 static void
1186 st_api_query_versions(struct st_api *stapi, struct st_manager *sm,
1187 struct st_config_options *options,
1188 int *gl_core_version,
1189 int *gl_compat_version,
1190 int *gl_es1_version,
1191 int *gl_es2_version)
1192 {
1193 *gl_core_version = get_version(sm->screen, options, API_OPENGL_CORE);
1194 *gl_compat_version = get_version(sm->screen, options, API_OPENGL_COMPAT);
1195 *gl_es1_version = get_version(sm->screen, options, API_OPENGLES);
1196 *gl_es2_version = get_version(sm->screen, options, API_OPENGLES2);
1197 }
1198
1199 static const struct st_api st_gl_api = {
1200 .name = "Mesa " PACKAGE_VERSION,
1201 .api = ST_API_OPENGL,
1202 .profile_mask = ST_PROFILE_DEFAULT_MASK |
1203 ST_PROFILE_OPENGL_CORE_MASK |
1204 ST_PROFILE_OPENGL_ES1_MASK |
1205 ST_PROFILE_OPENGL_ES2_MASK |
1206 0,
1207 .feature_mask = ST_API_FEATURE_MS_VISUALS_MASK,
1208 .destroy = st_api_destroy,
1209 .query_versions = st_api_query_versions,
1210 .create_context = st_api_create_context,
1211 .make_current = st_api_make_current,
1212 .get_current = st_api_get_current,
1213 .destroy_drawable = st_api_destroy_drawable,
1214 };
1215
1216 struct st_api *
1217 st_gl_api_create(void)
1218 {
1219 return (struct st_api *) &st_gl_api;
1220 }