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