diff options
Diffstat (limited to 'src/mesa/state_tracker/st_manager.c')
-rw-r--r-- | src/mesa/state_tracker/st_manager.c | 838 |
1 files changed, 440 insertions, 398 deletions
diff --git a/src/mesa/state_tracker/st_manager.c b/src/mesa/state_tracker/st_manager.c index 9e0f29a2ccd..a967cbc6089 100644 --- a/src/mesa/state_tracker/st_manager.c +++ b/src/mesa/state_tracker/st_manager.c @@ -29,6 +29,7 @@ #include "main/extensions.h" #include "main/context.h" #include "main/debug_output.h" +#include "main/framebuffer.h" #include "main/glthread.h" #include "main/texobj.h" #include "main/teximage.h" @@ -46,12 +47,10 @@ #include "st_extensions.h" #include "st_format.h" #include "st_cb_bitmap.h" -#include "st_cb_fbo.h" #include "st_cb_flush.h" #include "st_manager.h" #include "st_sampler_view.h" - -#include "state_tracker/st_gl_api.h" +#include "st_util.h" #include "pipe/p_context.h" #include "pipe/p_screen.h" @@ -63,14 +62,31 @@ #include "util/u_surface.h" #include "util/list.h" #include "util/u_memory.h" +#include "util/perf/cpu_trace.h" struct hash_table; -struct st_manager_private + +struct st_screen { - struct hash_table *stfbi_ht; /* framebuffer iface objects hash table */ + struct hash_table *drawable_ht; /* pipe_frontend_drawable objects hash table */ simple_mtx_t st_mutex; }; +/** + * Cast wrapper to convert a struct gl_framebuffer to an gl_framebuffer. + * Return NULL if the struct gl_framebuffer is a user-created framebuffer. + * We'll only return non-null for window system framebuffers. + * Note that this function may fail. + */ +static inline struct gl_framebuffer * +st_ws_framebuffer(struct gl_framebuffer *fb) +{ + /* FBO cannot be casted. See st_new_framebuffer */ + if (fb && _mesa_is_winsys_fbo(fb) && + fb != _mesa_get_incomplete_framebuffer()) + return fb; + return NULL; +} /** * Map an attachment to a buffer index. @@ -150,23 +166,23 @@ buffer_index_to_attachment(gl_buffer_index index) */ static void st_context_validate(struct st_context *st, - struct st_framebuffer *stdraw, - struct st_framebuffer *stread) + struct gl_framebuffer *stdraw, + struct gl_framebuffer *stread) { if (stdraw && stdraw->stamp != st->draw_stamp) { - st->dirty |= ST_NEW_FRAMEBUFFER; - _mesa_resize_framebuffer(st->ctx, &stdraw->Base, - stdraw->Base.Width, - stdraw->Base.Height); + st->ctx->NewDriverState |= ST_NEW_FRAMEBUFFER; + _mesa_resize_framebuffer(st->ctx, stdraw, + stdraw->Width, + stdraw->Height); st->draw_stamp = stdraw->stamp; } if (stread && stread->stamp != st->read_stamp) { if (stread != stdraw) { - st->dirty |= ST_NEW_FRAMEBUFFER; - _mesa_resize_framebuffer(st->ctx, &stread->Base, - stread->Base.Width, - stread->Base.Height); + st->ctx->NewDriverState |= ST_NEW_FRAMEBUFFER; + _mesa_resize_framebuffer(st->ctx, stread, + stread->Width, + stread->Height); } st->read_stamp = stread->stamp; } @@ -174,22 +190,22 @@ st_context_validate(struct st_context *st, void -st_set_ws_renderbuffer_surface(struct st_renderbuffer *strb, +st_set_ws_renderbuffer_surface(struct gl_renderbuffer *rb, struct pipe_surface *surf) { - pipe_surface_reference(&strb->surface_srgb, NULL); - pipe_surface_reference(&strb->surface_linear, NULL); + pipe_surface_reference(&rb->surface_srgb, NULL); + pipe_surface_reference(&rb->surface_linear, NULL); if (util_format_is_srgb(surf->format)) - pipe_surface_reference(&strb->surface_srgb, surf); + pipe_surface_reference(&rb->surface_srgb, surf); else - pipe_surface_reference(&strb->surface_linear, surf); + pipe_surface_reference(&rb->surface_linear, surf); - strb->surface = surf; /* just assign, don't ref */ - pipe_resource_reference(&strb->texture, surf->texture); + rb->surface = surf; /* just assign, don't ref */ + pipe_resource_reference(&rb->texture, surf->texture); - strb->Base.Width = surf->width; - strb->Base.Height = surf->height; + rb->Width = surf->width; + rb->Height = surf->height; } @@ -202,36 +218,37 @@ st_set_ws_renderbuffer_surface(struct st_renderbuffer *strb, * context). */ static void -st_framebuffer_validate(struct st_framebuffer *stfb, +st_framebuffer_validate(struct gl_framebuffer *stfb, struct st_context *st) { struct pipe_resource *textures[ST_ATTACHMENT_COUNT]; + struct pipe_resource *resolve = NULL; uint width, height; unsigned i; bool changed = false; int32_t new_stamp; - new_stamp = p_atomic_read(&stfb->iface->stamp); - if (stfb->iface_stamp == new_stamp) + new_stamp = p_atomic_read(&stfb->drawable->stamp); + if (stfb->drawable_stamp == new_stamp) return; memset(textures, 0, stfb->num_statts * sizeof(textures[0])); /* validate the fb */ do { - if (!stfb->iface->validate(&st->iface, stfb->iface, stfb->statts, - stfb->num_statts, textures)) + if (!stfb->drawable->validate(st, stfb->drawable, stfb->statts, + stfb->num_statts, textures, &resolve)) return; - stfb->iface_stamp = new_stamp; - new_stamp = p_atomic_read(&stfb->iface->stamp); - } while(stfb->iface_stamp != new_stamp); + stfb->drawable_stamp = new_stamp; + new_stamp = p_atomic_read(&stfb->drawable->stamp); + } while(stfb->drawable_stamp != new_stamp); - width = stfb->Base.Width; - height = stfb->Base.Height; + width = stfb->Width; + height = stfb->Height; for (i = 0; i < stfb->num_statts; i++) { - struct st_renderbuffer *strb; + struct gl_renderbuffer *rb; struct pipe_surface *ps, surf_tmpl; gl_buffer_index idx; @@ -244,9 +261,11 @@ st_framebuffer_validate(struct st_framebuffer *stfb, continue; } - strb = st_renderbuffer(stfb->Base.Attachment[idx].Renderbuffer); - assert(strb); - if (strb->texture == textures[i]) { + rb = stfb->Attachment[idx].Renderbuffer; + assert(rb); + if (rb->texture == textures[i] && + rb->Width == textures[i]->width0 && + rb->Height == textures[i]->height0) { pipe_resource_reference(&textures[i], NULL); continue; } @@ -254,30 +273,44 @@ st_framebuffer_validate(struct st_framebuffer *stfb, u_surface_default_template(&surf_tmpl, textures[i]); ps = st->pipe->create_surface(st->pipe, textures[i], &surf_tmpl); if (ps) { - st_set_ws_renderbuffer_surface(strb, ps); + st_set_ws_renderbuffer_surface(rb, ps); pipe_surface_reference(&ps, NULL); changed = true; - width = strb->Base.Width; - height = strb->Base.Height; + width = rb->Width; + height = rb->Height; } pipe_resource_reference(&textures[i], NULL); } + changed |= resolve != stfb->resolve; + /* ref is removed here */ + pipe_resource_reference(&stfb->resolve, NULL); + /* ref is taken here */ + stfb->resolve = resolve; + if (changed) { ++stfb->stamp; - _mesa_resize_framebuffer(st->ctx, &stfb->Base, width, height); + _mesa_resize_framebuffer(st->ctx, stfb, width, height); } } +/** + * Return true if the visual has the specified buffers. + */ +static inline bool +st_visual_have_buffers(const struct st_visual *visual, unsigned mask) +{ + return ((visual->buffer_mask & mask) == mask); +} /** * Update the attachments to validate by looping the existing renderbuffers. */ static void -st_framebuffer_update_attachments(struct st_framebuffer *stfb) +st_framebuffer_update_attachments(struct gl_framebuffer *stfb) { gl_buffer_index idx; @@ -287,35 +320,160 @@ st_framebuffer_update_attachments(struct st_framebuffer *stfb) stfb->statts[i] = ST_ATTACHMENT_INVALID; for (idx = 0; idx < BUFFER_COUNT; idx++) { - struct st_renderbuffer *strb; + struct gl_renderbuffer *rb; enum st_attachment_type statt; - strb = st_renderbuffer(stfb->Base.Attachment[idx].Renderbuffer); - if (!strb || strb->software) + rb = stfb->Attachment[idx].Renderbuffer; + if (!rb || rb->software) continue; statt = buffer_index_to_attachment(idx); if (statt != ST_ATTACHMENT_INVALID && - st_visual_have_buffers(stfb->iface->visual, 1 << statt)) + st_visual_have_buffers(stfb->drawable->visual, 1 << statt)) stfb->statts[stfb->num_statts++] = statt; } stfb->stamp++; } +/** + * Allocate a renderbuffer for an on-screen window (not a user-created + * renderbuffer). The window system code determines the format. + */ +static struct gl_renderbuffer * +st_new_renderbuffer_fb(enum pipe_format format, unsigned samples, bool sw) +{ + struct gl_renderbuffer *rb; + + rb = CALLOC_STRUCT(gl_renderbuffer); + if (!rb) { + _mesa_error(NULL, GL_OUT_OF_MEMORY, "creating renderbuffer"); + return NULL; + } + + _mesa_init_renderbuffer(rb, 0); + rb->NumSamples = samples; + rb->NumStorageSamples = samples; + rb->Format = st_pipe_format_to_mesa_format(format); + rb->_BaseFormat = _mesa_get_format_base_format(rb->Format); + rb->software = sw; + + switch (format) { + case PIPE_FORMAT_B10G10R10A2_UNORM: + case PIPE_FORMAT_R10G10B10A2_UNORM: + rb->InternalFormat = GL_RGB10_A2; + break; + case PIPE_FORMAT_R10G10B10X2_UNORM: + case PIPE_FORMAT_B10G10R10X2_UNORM: + rb->InternalFormat = GL_RGB10; + break; + case PIPE_FORMAT_R8G8B8A8_UNORM: + case PIPE_FORMAT_B8G8R8A8_UNORM: + case PIPE_FORMAT_A8R8G8B8_UNORM: + rb->InternalFormat = GL_RGBA8; + break; + case PIPE_FORMAT_R8G8B8X8_UNORM: + case PIPE_FORMAT_B8G8R8X8_UNORM: + case PIPE_FORMAT_X8R8G8B8_UNORM: + case PIPE_FORMAT_R8G8B8_UNORM: + rb->InternalFormat = GL_RGB8; + break; + case PIPE_FORMAT_R8G8B8A8_SRGB: + case PIPE_FORMAT_B8G8R8A8_SRGB: + case PIPE_FORMAT_A8R8G8B8_SRGB: + rb->InternalFormat = GL_SRGB8_ALPHA8; + break; + case PIPE_FORMAT_R8G8B8X8_SRGB: + case PIPE_FORMAT_B8G8R8X8_SRGB: + case PIPE_FORMAT_X8R8G8B8_SRGB: + rb->InternalFormat = GL_SRGB8; + break; + case PIPE_FORMAT_B5G5R5A1_UNORM: + rb->InternalFormat = GL_RGB5_A1; + break; + case PIPE_FORMAT_B4G4R4A4_UNORM: + rb->InternalFormat = GL_RGBA4; + break; + case PIPE_FORMAT_B5G6R5_UNORM: + rb->InternalFormat = GL_RGB565; + break; + case PIPE_FORMAT_Z16_UNORM: + rb->InternalFormat = GL_DEPTH_COMPONENT16; + break; + case PIPE_FORMAT_Z32_UNORM: + rb->InternalFormat = GL_DEPTH_COMPONENT32; + break; + case PIPE_FORMAT_Z24_UNORM_S8_UINT: + case PIPE_FORMAT_S8_UINT_Z24_UNORM: + rb->InternalFormat = GL_DEPTH24_STENCIL8_EXT; + break; + case PIPE_FORMAT_Z24X8_UNORM: + case PIPE_FORMAT_X8Z24_UNORM: + rb->InternalFormat = GL_DEPTH_COMPONENT24; + break; + case PIPE_FORMAT_S8_UINT: + rb->InternalFormat = GL_STENCIL_INDEX8_EXT; + break; + case PIPE_FORMAT_R16G16B16A16_SNORM: + /* accum buffer */ + rb->InternalFormat = GL_RGBA16_SNORM; + break; + case PIPE_FORMAT_R16G16B16A16_UNORM: + rb->InternalFormat = GL_RGBA16; + break; + case PIPE_FORMAT_R16G16B16_UNORM: + rb->InternalFormat = GL_RGB16; + break; + case PIPE_FORMAT_R8_UNORM: + rb->InternalFormat = GL_R8; + break; + case PIPE_FORMAT_R8G8_UNORM: + rb->InternalFormat = GL_RG8; + break; + case PIPE_FORMAT_R16_UNORM: + rb->InternalFormat = GL_R16; + break; + case PIPE_FORMAT_R16G16_UNORM: + rb->InternalFormat = GL_RG16; + break; + case PIPE_FORMAT_R32G32B32A32_FLOAT: + rb->InternalFormat = GL_RGBA32F; + break; + case PIPE_FORMAT_R32G32B32X32_FLOAT: + case PIPE_FORMAT_R32G32B32_FLOAT: + rb->InternalFormat = GL_RGB32F; + break; + case PIPE_FORMAT_R16G16B16A16_FLOAT: + rb->InternalFormat = GL_RGBA16F; + break; + case PIPE_FORMAT_R16G16B16X16_FLOAT: + rb->InternalFormat = GL_RGB16F; + break; + default: + _mesa_problem(NULL, + "Unexpected format %s in st_new_renderbuffer_fb", + util_format_name(format)); + FREE(rb); + return NULL; + } + + rb->surface = NULL; + + return rb; +} /** * Add a renderbuffer to the framebuffer. The framebuffer is one that * corresponds to a window and is not a user-created FBO. */ static bool -st_framebuffer_add_renderbuffer(struct st_framebuffer *stfb, +st_framebuffer_add_renderbuffer(struct gl_framebuffer *stfb, gl_buffer_index idx, bool prefer_srgb) { struct gl_renderbuffer *rb; enum pipe_format format; bool sw; - assert(_mesa_is_winsys_fbo(&stfb->Base)); + assert(_mesa_is_winsys_fbo(stfb)); /* do not distinguish depth/stencil buffers */ if (idx == BUFFER_STENCIL) @@ -323,15 +481,15 @@ st_framebuffer_add_renderbuffer(struct st_framebuffer *stfb, switch (idx) { case BUFFER_DEPTH: - format = stfb->iface->visual->depth_stencil_format; + format = stfb->drawable->visual->depth_stencil_format; sw = false; break; case BUFFER_ACCUM: - format = stfb->iface->visual->accum_format; + format = stfb->drawable->visual->accum_format; sw = true; break; default: - format = stfb->iface->visual->color_format; + format = stfb->drawable->visual->color_format; if (prefer_srgb) format = util_format_srgb(format); sw = false; @@ -341,26 +499,26 @@ st_framebuffer_add_renderbuffer(struct st_framebuffer *stfb, if (format == PIPE_FORMAT_NONE) return false; - rb = st_new_renderbuffer_fb(format, stfb->iface->visual->samples, sw); + rb = st_new_renderbuffer_fb(format, stfb->drawable->visual->samples, sw); if (!rb) return false; if (idx != BUFFER_DEPTH) { - _mesa_attach_and_own_rb(&stfb->Base, idx, rb); + _mesa_attach_and_own_rb(stfb, idx, rb); return true; } bool rb_ownership_taken = false; if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_ZS, 0)) { - _mesa_attach_and_own_rb(&stfb->Base, BUFFER_DEPTH, rb); + _mesa_attach_and_own_rb(stfb, BUFFER_DEPTH, rb); rb_ownership_taken = true; } if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_ZS, 1)) { if (rb_ownership_taken) - _mesa_attach_and_reference_rb(&stfb->Base, BUFFER_STENCIL, rb); + _mesa_attach_and_reference_rb(stfb, BUFFER_STENCIL, rb); else - _mesa_attach_and_own_rb(&stfb->Base, BUFFER_STENCIL, rb); + _mesa_attach_and_own_rb(stfb, BUFFER_STENCIL, rb); } return true; @@ -400,6 +558,7 @@ st_visual_to_context_mode(const struct st_visual *visual, mode->rgbBits = mode->redBits + mode->greenBits + mode->blueBits + mode->alphaBits; mode->sRGBCapable = util_format_is_srgb(visual->color_format); + mode->floatMode = util_format_is_float(visual->color_format); } if (visual->depth_stencil_format != PIPE_FORMAT_NONE) { @@ -435,23 +594,23 @@ st_visual_to_context_mode(const struct st_visual *visual, /** * Create a framebuffer from a manager interface. */ -static struct st_framebuffer * +static struct gl_framebuffer * st_framebuffer_create(struct st_context *st, - struct st_framebuffer_iface *stfbi) + struct pipe_frontend_drawable *drawable) { - struct st_framebuffer *stfb; + struct gl_framebuffer *stfb; struct gl_config mode; gl_buffer_index idx; bool prefer_srgb = false; - if (!stfbi) + if (!drawable) return NULL; - stfb = CALLOC_STRUCT(st_framebuffer); + stfb = CALLOC_STRUCT(gl_framebuffer); if (!stfb) return NULL; - st_visual_to_context_mode(stfbi->visual, &mode); + st_visual_to_context_mode(drawable->visual, &mode); /* * For desktop GL, sRGB framebuffer write is controlled by both the @@ -475,13 +634,13 @@ st_framebuffer_create(struct st_context *st, if (_mesa_has_EXT_framebuffer_sRGB(st->ctx)) { struct pipe_screen *screen = st->screen; const enum pipe_format srgb_format = - util_format_srgb(stfbi->visual->color_format); + util_format_srgb(drawable->visual->color_format); if (srgb_format != PIPE_FORMAT_NONE && st_pipe_format_to_mesa_format(srgb_format) != MESA_FORMAT_NONE && screen->is_format_supported(screen, srgb_format, - PIPE_TEXTURE_2D, stfbi->visual->samples, - stfbi->visual->samples, + PIPE_TEXTURE_2D, drawable->visual->samples, + drawable->visual->samples, (PIPE_BIND_DISPLAY_TARGET | PIPE_BIND_RENDER_TARGET))) { mode.sRGBCapable = GL_TRUE; @@ -493,16 +652,16 @@ st_framebuffer_create(struct st_context *st, } } - _mesa_initialize_window_framebuffer(&stfb->Base, &mode); + _mesa_initialize_window_framebuffer(stfb, &mode); - stfb->iface = stfbi; - stfb->iface_ID = stfbi->ID; - stfb->iface_stamp = p_atomic_read(&stfbi->stamp) - 1; + stfb->drawable = drawable; + stfb->drawable_ID = drawable->ID; + stfb->drawable_stamp = p_atomic_read(&drawable->stamp) - 1; /* add the color buffer */ - idx = stfb->Base._ColorDrawBufferIndexes[0]; + idx = stfb->_ColorDrawBufferIndexes[0]; if (!st_framebuffer_add_renderbuffer(stfb, idx, prefer_srgb)) { - free(stfb); + FREE(stfb); return NULL; } @@ -516,90 +675,78 @@ st_framebuffer_create(struct st_context *st, } -/** - * Reference a framebuffer. - */ -void -st_framebuffer_reference(struct st_framebuffer **ptr, - struct st_framebuffer *stfb) -{ - struct gl_framebuffer *fb = stfb ? &stfb->Base : NULL; - _mesa_reference_framebuffer((struct gl_framebuffer **) ptr, fb); -} - - static uint32_t -st_framebuffer_iface_hash(const void *key) +drawable_hash(const void *key) { return (uintptr_t)key; } static bool -st_framebuffer_iface_equal(const void *a, const void *b) +drawable_equal(const void *a, const void *b) { - return (struct st_framebuffer_iface *)a == (struct st_framebuffer_iface *)b; + return (struct pipe_frontend_drawable *)a == (struct pipe_frontend_drawable *)b; } static bool -st_framebuffer_iface_lookup(struct st_manager *smapi, - const struct st_framebuffer_iface *stfbi) +drawable_lookup(struct pipe_frontend_screen *fscreen, + const struct pipe_frontend_drawable *drawable) { - struct st_manager_private *smPriv = - (struct st_manager_private *)smapi->st_manager_private; + struct st_screen *screen = + (struct st_screen *)fscreen->st_screen; struct hash_entry *entry; - assert(smPriv); - assert(smPriv->stfbi_ht); + assert(screen); + assert(screen->drawable_ht); - simple_mtx_lock(&smPriv->st_mutex); - entry = _mesa_hash_table_search(smPriv->stfbi_ht, stfbi); - simple_mtx_unlock(&smPriv->st_mutex); + simple_mtx_lock(&screen->st_mutex); + entry = _mesa_hash_table_search(screen->drawable_ht, drawable); + simple_mtx_unlock(&screen->st_mutex); return entry != NULL; } static bool -st_framebuffer_iface_insert(struct st_manager *smapi, - struct st_framebuffer_iface *stfbi) +drawable_insert(struct pipe_frontend_screen *fscreen, + struct pipe_frontend_drawable *drawable) { - struct st_manager_private *smPriv = - (struct st_manager_private *)smapi->st_manager_private; + struct st_screen *screen = + (struct st_screen *)fscreen->st_screen; struct hash_entry *entry; - assert(smPriv); - assert(smPriv->stfbi_ht); + assert(screen); + assert(screen->drawable_ht); - simple_mtx_lock(&smPriv->st_mutex); - entry = _mesa_hash_table_insert(smPriv->stfbi_ht, stfbi, stfbi); - simple_mtx_unlock(&smPriv->st_mutex); + simple_mtx_lock(&screen->st_mutex); + entry = _mesa_hash_table_insert(screen->drawable_ht, drawable, drawable); + simple_mtx_unlock(&screen->st_mutex); return entry != NULL; } static void -st_framebuffer_iface_remove(struct st_manager *smapi, - struct st_framebuffer_iface *stfbi) +drawable_remove(struct pipe_frontend_screen *fscreen, + struct pipe_frontend_drawable *drawable) { - struct st_manager_private *smPriv = - (struct st_manager_private *)smapi->st_manager_private; + struct st_screen *screen = + (struct st_screen *)fscreen->st_screen; struct hash_entry *entry; - if (!smPriv || !smPriv->stfbi_ht) + if (!screen || !screen->drawable_ht) return; - simple_mtx_lock(&smPriv->st_mutex); - entry = _mesa_hash_table_search(smPriv->stfbi_ht, stfbi); + simple_mtx_lock(&screen->st_mutex); + entry = _mesa_hash_table_search(screen->drawable_ht, drawable); if (!entry) goto unlock; - _mesa_hash_table_remove(smPriv->stfbi_ht, entry); + _mesa_hash_table_remove(screen->drawable_ht, entry); unlock: - simple_mtx_unlock(&smPriv->st_mutex); + simple_mtx_unlock(&screen->st_mutex); } @@ -607,14 +754,13 @@ unlock: * The framebuffer interface object is no longer valid. * Remove the object from the framebuffer interface hash table. */ -static void -st_api_destroy_drawable(struct st_api *stapi, - struct st_framebuffer_iface *stfbi) +void +st_api_destroy_drawable(struct pipe_frontend_drawable *drawable) { - if (!stfbi) + if (!drawable) return; - st_framebuffer_iface_remove(stfbi->state_manager, stfbi); + drawable_remove(drawable->fscreen, drawable); } @@ -625,16 +771,15 @@ st_api_destroy_drawable(struct st_api *stapi, static void st_framebuffers_purge(struct st_context *st) { - struct st_context_iface *st_iface = &st->iface; - struct st_manager *smapi = st_iface->state_manager; - struct st_framebuffer *stfb, *next; + struct pipe_frontend_screen *fscreen = st->frontend_screen; + struct gl_framebuffer *stfb, *next; - assert(smapi); + assert(fscreen); LIST_FOR_EACH_ENTRY_SAFE_REV(stfb, next, &st->winsys_buffers, head) { - struct st_framebuffer_iface *stfbi = stfb->iface; + struct pipe_frontend_drawable *drawable = stfb->drawable; - assert(stfbi); + assert(drawable); /** * If the corresponding framebuffer interface object no longer exists, @@ -642,23 +787,23 @@ st_framebuffers_purge(struct st_context *st) * and unreference the framebuffer object, so its resources can be * deleted. */ - if (!st_framebuffer_iface_lookup(smapi, stfbi)) { + if (!drawable_lookup(fscreen, drawable)) { list_del(&stfb->head); - st_framebuffer_reference(&stfb, NULL); + _mesa_reference_framebuffer(&stfb, NULL); } } } -static void -st_context_flush(struct st_context_iface *stctxi, unsigned flags, +void +st_context_flush(struct st_context *st, unsigned flags, struct pipe_fence_handle **fence, - void (*before_flush_cb) (void*), - void* args) + void (*before_flush_cb) (void*), void* args) { - struct st_context *st = (struct st_context *) stctxi; unsigned pipe_flags = 0; + MESA_TRACE_FUNC(); + if (flags & ST_FLUSH_END_OF_FRAME) pipe_flags |= PIPE_FLUSH_END_OF_FRAME; if (flags & ST_FLUSH_FENCE_FD) @@ -677,70 +822,42 @@ st_context_flush(struct st_context_iface *stctxi, unsigned flags, if ((flags & ST_FLUSH_WAIT) && fence && *fence) { st->screen->fence_finish(st->screen, NULL, *fence, - PIPE_TIMEOUT_INFINITE); + OS_TIMEOUT_INFINITE); st->screen->fence_reference(st->screen, fence, NULL); } if (flags & ST_FLUSH_FRONT) st_manager_flush_frontbuffer(st); - - /* DRI3 changes the framebuffer after SwapBuffers, but we need to invoke - * st_manager_validate_framebuffers to notice that. - * - * Set gfx_shaders_may_be_dirty to invoke st_validate_state in the next - * draw call, which will invoke st_manager_validate_framebuffers, but it - * won't dirty states if there is no change. - */ - if (flags & ST_FLUSH_END_OF_FRAME) - st->gfx_shaders_may_be_dirty = true; } -static bool -st_context_teximage(struct st_context_iface *stctxi, - enum st_texture_type tex_type, +/** + * Replace the texture image of a texture object at the specified level. + * + * This is only for GLX_EXT_texture_from_pixmap and equivalent features + * in EGL and WGL. + */ +bool +st_context_teximage(struct st_context *st, GLenum target, int level, enum pipe_format pipe_format, struct pipe_resource *tex, bool mipmap) { - struct st_context *st = (struct st_context *) stctxi; struct gl_context *ctx = st->ctx; struct gl_texture_object *texObj; struct gl_texture_image *texImage; - struct st_texture_object *stObj; - struct st_texture_image *stImage; GLenum internalFormat; GLuint width, height, depth; - GLenum target; - - switch (tex_type) { - case ST_TEXTURE_1D: - target = GL_TEXTURE_1D; - break; - case ST_TEXTURE_2D: - target = GL_TEXTURE_2D; - break; - case ST_TEXTURE_3D: - target = GL_TEXTURE_3D; - break; - case ST_TEXTURE_RECT: - target = GL_TEXTURE_RECTANGLE_ARB; - break; - default: - return FALSE; - } texObj = _mesa_get_current_tex_object(ctx, target); _mesa_lock_texture(ctx, texObj); - stObj = st_texture_object(texObj); /* switch to surface based */ - if (!stObj->surface_based) { + if (!texObj->surface_based) { _mesa_clear_texture_object(ctx, texObj, NULL); - stObj->surface_based = GL_TRUE; + texObj->surface_based = GL_TRUE; } texImage = _mesa_get_tex_image(ctx, texObj, target, level); - stImage = st_texture_image(texImage); if (tex) { mesa_format texFormat = st_pipe_format_to_mesa_format(pipe_format); @@ -772,167 +889,104 @@ st_context_teximage(struct st_context_iface *stctxi, _mesa_clear_texture_image(ctx, texImage); width = height = depth = 0; } + _mesa_update_texture_object_swizzle(ctx, texObj); - pipe_resource_reference(&stObj->pt, tex); - st_texture_release_all_sampler_views(st, stObj); - pipe_resource_reference(&stImage->pt, tex); - stObj->surface_format = pipe_format; + pipe_resource_reference(&texObj->pt, tex); + st_texture_release_all_sampler_views(st, texObj); + pipe_resource_reference(&texImage->pt, tex); + texObj->surface_format = pipe_format; - stObj->needs_validation = true; + texObj->needs_validation = true; _mesa_dirty_texobj(ctx, texObj); + ctx->Shared->HasExternallySharedImages = true; _mesa_unlock_texture(ctx, texObj); return true; } -static void -st_context_copy(struct st_context_iface *stctxi, - struct st_context_iface *stsrci, unsigned mask) -{ - struct st_context *st = (struct st_context *) stctxi; - struct st_context *src = (struct st_context *) stsrci; - - _mesa_copy_context(src->ctx, st->ctx, mask); -} - - -static bool -st_context_share(struct st_context_iface *stctxi, - struct st_context_iface *stsrci) -{ - struct st_context *st = (struct st_context *) stctxi; - struct st_context *src = (struct st_context *) stsrci; - - return _mesa_share_state(st->ctx, src->ctx); -} - - -static void -st_context_destroy(struct st_context_iface *stctxi) -{ - struct st_context *st = (struct st_context *) stctxi; - st_destroy_context(st); -} - - -static void -st_start_thread(struct st_context_iface *stctxi) -{ - struct st_context *st = (struct st_context *) stctxi; - - _mesa_glthread_init(st->ctx); -} - - -static void -st_thread_finish(struct st_context_iface *stctxi) -{ - struct st_context *st = (struct st_context *) stctxi; - - _mesa_glthread_finish(st->ctx); -} - - -static void -st_context_invalidate_state(struct st_context_iface *stctxi, - unsigned flags) +/** + * Invalidate states to notify the frontend that driver states have been + * changed behind its back. + */ +void +st_context_invalidate_state(struct st_context *st, unsigned flags) { - struct st_context *st = (struct st_context *) stctxi; + struct gl_context *ctx = st->ctx; if (flags & ST_INVALIDATE_FS_SAMPLER_VIEWS) - st->dirty |= ST_NEW_FS_SAMPLER_VIEWS; + ctx->NewDriverState |= ST_NEW_FS_SAMPLER_VIEWS; if (flags & ST_INVALIDATE_FS_CONSTBUF0) - st->dirty |= ST_NEW_FS_CONSTANTS; + ctx->NewDriverState |= ST_NEW_FS_CONSTANTS; if (flags & ST_INVALIDATE_VS_CONSTBUF0) - st->dirty |= ST_NEW_VS_CONSTANTS; - if (flags & ST_INVALIDATE_VERTEX_BUFFERS) - st->dirty |= ST_NEW_VERTEX_ARRAYS; + ctx->NewDriverState |= ST_NEW_VS_CONSTANTS; + if (flags & ST_INVALIDATE_VERTEX_BUFFERS) { + ctx->Array.NewVertexElements = true; + ctx->NewDriverState |= ST_NEW_VERTEX_ARRAYS; + } + if (flags & ST_INVALIDATE_FB_STATE) + ctx->NewDriverState |= ST_NEW_FB_STATE; } -static void -st_manager_destroy(struct st_manager *smapi) +void +st_screen_destroy(struct pipe_frontend_screen *fscreen) { - struct st_manager_private *smPriv = smapi->st_manager_private; + struct st_screen *screen = fscreen->st_screen; - if (smPriv && smPriv->stfbi_ht) { - _mesa_hash_table_destroy(smPriv->stfbi_ht, NULL); - simple_mtx_destroy(&smPriv->st_mutex); - free(smPriv); - smapi->st_manager_private = NULL; + if (screen && screen->drawable_ht) { + _mesa_hash_table_destroy(screen->drawable_ht, NULL); + simple_mtx_destroy(&screen->st_mutex); + FREE(screen); + fscreen->st_screen = NULL; } } -static struct st_context_iface * -st_api_create_context(struct st_api *stapi, struct st_manager *smapi, +/** + * Create a rendering context. + */ +struct st_context * +st_api_create_context(struct pipe_frontend_screen *fscreen, const struct st_context_attribs *attribs, enum st_context_error *error, - struct st_context_iface *shared_stctxi) + struct st_context *shared_ctx) { - struct st_context *shared_ctx = (struct st_context *) shared_stctxi; struct st_context *st; struct pipe_context *pipe; struct gl_config mode, *mode_ptr = &mode; - gl_api api; bool no_error = false; - unsigned ctx_flags = PIPE_CONTEXT_PREFER_THREADED; - if (!(stapi->profile_mask & (1 << attribs->profile))) - return NULL; - - switch (attribs->profile) { - case ST_PROFILE_DEFAULT: - api = API_OPENGL_COMPAT; - break; - case ST_PROFILE_OPENGL_ES1: - api = API_OPENGLES; - break; - case ST_PROFILE_OPENGL_ES2: - api = API_OPENGLES2; - break; - case ST_PROFILE_OPENGL_CORE: - api = API_OPENGL_CORE; - break; - default: - *error = ST_CONTEXT_ERROR_BAD_API; - return NULL; - } - - _mesa_initialize(); + _mesa_initialize(attribs->options.mesa_extension_override); /* Create a hash table for the framebuffer interface objects * if it has not been created for this st manager. */ - if (smapi->st_manager_private == NULL) { - struct st_manager_private *smPriv; - - smPriv = CALLOC_STRUCT(st_manager_private); - simple_mtx_init(&smPriv->st_mutex, mtx_plain); - smPriv->stfbi_ht = _mesa_hash_table_create(NULL, - st_framebuffer_iface_hash, - st_framebuffer_iface_equal); - smapi->st_manager_private = smPriv; - smapi->destroy = st_manager_destroy; + if (fscreen->st_screen == NULL) { + struct st_screen *screen; + + screen = CALLOC_STRUCT(st_screen); + simple_mtx_init(&screen->st_mutex, mtx_plain); + screen->drawable_ht = _mesa_hash_table_create(NULL, + drawable_hash, + drawable_equal); + fscreen->st_screen = screen; } - if (attribs->flags & ST_CONTEXT_FLAG_ROBUST_ACCESS) - ctx_flags |= PIPE_CONTEXT_ROBUST_BUFFER_ACCESS; - if (attribs->flags & ST_CONTEXT_FLAG_NO_ERROR) no_error = true; - if (attribs->flags & ST_CONTEXT_FLAG_LOW_PRIORITY) - ctx_flags |= PIPE_CONTEXT_LOW_PRIORITY; - else if (attribs->flags & ST_CONTEXT_FLAG_HIGH_PRIORITY) - ctx_flags |= PIPE_CONTEXT_HIGH_PRIORITY; - - if (attribs->flags & ST_CONTEXT_FLAG_RESET_NOTIFICATION_ENABLED) - ctx_flags |= PIPE_CONTEXT_LOSE_CONTEXT_ON_RESET; + /* OpenGL ES 2.0+ does not support sampler state LOD bias. If we are creating + * a GLES context, communicate that to the the driver to allow optimization. + */ + bool is_gles = attribs->profile == API_OPENGLES2; + unsigned lod_bias_flag = is_gles ? PIPE_CONTEXT_NO_LOD_BIAS : 0; - pipe = smapi->screen->context_create(smapi->screen, NULL, ctx_flags); + pipe = fscreen->screen->context_create(fscreen->screen, NULL, + PIPE_CONTEXT_PREFER_THREADED | + lod_bias_flag | + attribs->context_flags); if (!pipe) { *error = ST_CONTEXT_ERROR_NO_MEMORY; return NULL; @@ -941,9 +995,9 @@ st_api_create_context(struct st_api *stapi, struct st_manager *smapi, st_visual_to_context_mode(&attribs->visual, &mode); if (attribs->visual.color_format == PIPE_FORMAT_NONE) mode_ptr = NULL; - st = st_create_context(api, pipe, mode_ptr, shared_ctx, + st = st_create_context(attribs->profile, pipe, mode_ptr, shared_ctx, &attribs->options, no_error, - !!smapi->validate_egl_image); + !!fscreen->validate_egl_image); if (!st) { *error = ST_CONTEXT_ERROR_NO_MEMORY; pipe->destroy(pipe); @@ -960,16 +1014,18 @@ st_api_create_context(struct st_api *stapi, struct st_manager *smapi, } if (st->ctx->Const.ContextFlags & GL_CONTEXT_FLAG_DEBUG_BIT) { - st_update_debug_callback(st); + _mesa_update_debug_callback(st->ctx); } if (attribs->flags & ST_CONTEXT_FLAG_FORWARD_COMPATIBLE) st->ctx->Const.ContextFlags |= GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT; - if (attribs->flags & ST_CONTEXT_FLAG_ROBUST_ACCESS) { + + if (attribs->context_flags & PIPE_CONTEXT_ROBUST_BUFFER_ACCESS) { st->ctx->Const.ContextFlags |= GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT_ARB; st->ctx->Const.RobustAccess = GL_TRUE; } - if (attribs->flags & ST_CONTEXT_FLAG_RESET_NOTIFICATION_ENABLED) { + + if (attribs->context_flags & PIPE_CONTEXT_LOSE_CONTEXT_ON_RESET) { st->ctx->Const.ResetStrategy = GL_LOSE_CONTEXT_ON_RESET_ARB; st_install_device_reset_callback(st); } @@ -990,78 +1046,68 @@ st_api_create_context(struct st_api *stapi, struct st_manager *smapi, st->can_scissor_clear = !!st->screen->get_param(st->screen, PIPE_CAP_CLEAR_SCISSORED); - st->invalidate_on_gl_viewport = - smapi->get_param(smapi, ST_MANAGER_BROKEN_INVALIDATE); - - st->iface.destroy = st_context_destroy; - st->iface.flush = st_context_flush; - st->iface.teximage = st_context_teximage; - st->iface.copy = st_context_copy; - st->iface.share = st_context_share; - st->iface.start_thread = st_start_thread; - st->iface.thread_finish = st_thread_finish; - st->iface.invalidate_state = st_context_invalidate_state; - st->iface.st_context_private = (void *) smapi; - st->iface.cso_context = st->cso_context; - st->iface.pipe = st->pipe; - st->iface.state_manager = smapi; + st->ctx->invalidate_on_gl_viewport = + fscreen->get_param(fscreen, ST_MANAGER_BROKEN_INVALIDATE); + + st->frontend_screen = fscreen; if (st->ctx->IntelBlackholeRender && st->screen->get_param(st->screen, PIPE_CAP_FRONTEND_NOOP)) st->pipe->set_frontend_noop(st->pipe, st->ctx->IntelBlackholeRender); *error = ST_CONTEXT_SUCCESS; - return &st->iface; + return st; } -static struct st_context_iface * -st_api_get_current(struct st_api *stapi) +/** + * Get the currently bound context in the calling thread. + */ +struct st_context * +st_api_get_current(void) { GET_CURRENT_CONTEXT(ctx); - struct st_context *st = ctx ? ctx->st : NULL; - return st ? &st->iface : NULL; + return ctx ? ctx->st : NULL; } -static struct st_framebuffer * +static struct gl_framebuffer * st_framebuffer_reuse_or_create(struct st_context *st, - struct gl_framebuffer *fb, - struct st_framebuffer_iface *stfbi) + struct pipe_frontend_drawable *drawable) { - struct st_framebuffer *cur = NULL, *stfb = NULL; + struct gl_framebuffer *cur = NULL, *stfb = NULL; - if (!stfbi) + if (!drawable) return NULL; /* Check if there is already a framebuffer object for the specified * framebuffer interface in this context. If there is one, use it. */ LIST_FOR_EACH_ENTRY(cur, &st->winsys_buffers, head) { - if (cur->iface_ID == stfbi->ID) { - st_framebuffer_reference(&stfb, cur); + if (cur->drawable_ID == drawable->ID) { + _mesa_reference_framebuffer(&stfb, cur); break; } } /* If there is not already a framebuffer object, create one */ if (stfb == NULL) { - cur = st_framebuffer_create(st, stfbi); + cur = st_framebuffer_create(st, drawable); if (cur) { /* add the referenced framebuffer interface object to * the framebuffer interface object hash table. */ - if (!st_framebuffer_iface_insert(stfbi->state_manager, stfbi)) { - st_framebuffer_reference(&cur, NULL); + if (!drawable_insert(drawable->fscreen, drawable)) { + _mesa_reference_framebuffer(&cur, NULL); return NULL; } /* add to the context's winsys buffers list */ list_add(&cur->head, &st->winsys_buffers); - st_framebuffer_reference(&stfb, cur); + _mesa_reference_framebuffer(&stfb, cur); } } @@ -1069,29 +1115,31 @@ st_framebuffer_reuse_or_create(struct st_context *st, } -static bool -st_api_make_current(struct st_api *stapi, struct st_context_iface *stctxi, - struct st_framebuffer_iface *stdrawi, - struct st_framebuffer_iface *streadi) +/** + * Bind the context to the calling thread with draw and read as drawables. + * + * The framebuffers might be NULL, meaning the context is surfaceless. + */ +bool +st_api_make_current(struct st_context *st, + struct pipe_frontend_drawable *stdrawi, + struct pipe_frontend_drawable *streadi) { - struct st_context *st = (struct st_context *) stctxi; - struct st_framebuffer *stdraw, *stread; + struct gl_framebuffer *stdraw, *stread; bool ret; if (st) { /* reuse or create the draw fb */ - stdraw = st_framebuffer_reuse_or_create(st, - st->ctx->WinSysDrawBuffer, stdrawi); + stdraw = st_framebuffer_reuse_or_create(st, stdrawi); if (streadi != stdrawi) { /* do the same for the read fb */ - stread = st_framebuffer_reuse_or_create(st, - st->ctx->WinSysReadBuffer, streadi); + stread = st_framebuffer_reuse_or_create(st, streadi); } else { stread = NULL; /* reuse the draw fb for the read fb */ if (stdraw) - st_framebuffer_reference(&stread, stdraw); + _mesa_reference_framebuffer(&stread, stdraw); } /* If framebuffers were asked for, we'd better have allocated them */ @@ -1103,7 +1151,7 @@ st_api_make_current(struct st_api *stapi, struct st_context_iface *stctxi, if (stread != stdraw) st_framebuffer_validate(stread, st); - ret = _mesa_make_current(st->ctx, &stdraw->Base, &stread->Base); + ret = _mesa_make_current(st->ctx, stdraw, stread); st->draw_stamp = stdraw->stamp - 1; st->read_stamp = stread->stamp - 1; @@ -1114,8 +1162,8 @@ st_api_make_current(struct st_api *stapi, struct st_context_iface *stctxi, ret = _mesa_make_current(st->ctx, incomplete, incomplete); } - st_framebuffer_reference(&stdraw, NULL); - st_framebuffer_reference(&stread, NULL); + _mesa_reference_framebuffer(&stdraw, NULL); + _mesa_reference_framebuffer(&stread, NULL); /* Purge the context's winsys_buffers list in case any * of the referenced drawables no longer exist. @@ -1142,20 +1190,14 @@ st_api_make_current(struct st_api *stapi, struct st_context_iface *stctxi, } -static void -st_api_destroy(struct st_api *stapi) -{ -} - - /** * Flush the front buffer if the current context renders to the front buffer. */ void st_manager_flush_frontbuffer(struct st_context *st) { - struct st_framebuffer *stfb = st_ws_framebuffer(st->ctx->DrawBuffer); - struct st_renderbuffer *strb = NULL; + struct gl_framebuffer *stfb = st_ws_framebuffer(st->ctx->DrawBuffer); + struct gl_renderbuffer *rb = NULL; if (!stfb) return; @@ -1165,29 +1207,27 @@ st_manager_flush_frontbuffer(struct st_context *st) * flushing. */ if (st->ctx->Visual.doubleBufferMode && - !stfb->Base.Visual.doubleBufferMode) + !stfb->Visual.doubleBufferMode) return; /* Check front buffer used at the GL API level. */ enum st_attachment_type statt = ST_ATTACHMENT_FRONT_LEFT; - strb = st_renderbuffer(stfb->Base.Attachment[BUFFER_FRONT_LEFT]. - Renderbuffer); - if (!strb) { + rb = stfb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer; + if (!rb) { /* Check back buffer redirected by EGL_KHR_mutable_render_buffer. */ statt = ST_ATTACHMENT_BACK_LEFT; - strb = st_renderbuffer(stfb->Base.Attachment[BUFFER_BACK_LEFT]. - Renderbuffer); + rb = stfb->Attachment[BUFFER_BACK_LEFT].Renderbuffer; } /* Do we have a front color buffer and has it been drawn to since last * frontbuffer flush? */ - if (strb && strb->defined && - stfb->iface->flush_front(&st->iface, stfb->iface, statt)) { - strb->defined = GL_FALSE; + if (rb && rb->defined && + stfb->drawable->flush_front(st, stfb->drawable, statt)) { + rb->defined = GL_FALSE; - /* Trigger an update of strb->defined on next draw */ - st->dirty |= ST_NEW_FB_STATE; + /* Trigger an update of rb->defined on next draw */ + st->ctx->NewDriverState |= ST_NEW_FB_STATE; } } @@ -1198,8 +1238,8 @@ st_manager_flush_frontbuffer(struct st_context *st) void st_manager_validate_framebuffers(struct st_context *st) { - struct st_framebuffer *stdraw = st_ws_framebuffer(st->ctx->DrawBuffer); - struct st_framebuffer *stread = st_ws_framebuffer(st->ctx->ReadBuffer); + struct gl_framebuffer *stdraw = st_ws_framebuffer(st->ctx->DrawBuffer); + struct gl_framebuffer *stread = st_ws_framebuffer(st->ctx->ReadBuffer); if (stdraw) st_framebuffer_validate(stdraw, st); @@ -1218,16 +1258,16 @@ st_manager_flush_swapbuffers(void) { GET_CURRENT_CONTEXT(ctx); struct st_context *st = (ctx) ? ctx->st : NULL; - struct st_framebuffer *stfb; + struct gl_framebuffer *stfb; if (!st) return; stfb = st_ws_framebuffer(ctx->DrawBuffer); - if (!stfb || !stfb->iface->flush_swapbuffers) + if (!stfb || !stfb->drawable->flush_swapbuffers) return; - stfb->iface->flush_swapbuffers(&st->iface, stfb->iface); + stfb->drawable->flush_swapbuffers(st, stfb->drawable); } @@ -1236,11 +1276,11 @@ st_manager_flush_swapbuffers(void) * not a user-created FBO. */ bool -st_manager_add_color_renderbuffer(struct st_context *st, +st_manager_add_color_renderbuffer(struct gl_context *ctx, struct gl_framebuffer *fb, gl_buffer_index idx) { - struct st_framebuffer *stfb = st_ws_framebuffer(fb); + struct gl_framebuffer *stfb = st_ws_framebuffer(fb); /* FBO */ if (!stfb) @@ -1248,7 +1288,7 @@ st_manager_add_color_renderbuffer(struct st_context *st, assert(_mesa_is_winsys_fbo(fb)); - if (stfb->Base.Attachment[idx].Renderbuffer) + if (stfb->Attachment[idx].Renderbuffer) return true; switch (idx) { @@ -1262,7 +1302,7 @@ st_manager_add_color_renderbuffer(struct st_context *st, } if (!st_framebuffer_add_renderbuffer(stfb, idx, - stfb->Base.Visual.sRGBCapable)) + stfb->Visual.sRGBCapable)) return false; st_framebuffer_update_attachments(stfb); @@ -1272,10 +1312,10 @@ st_manager_add_color_renderbuffer(struct st_context *st, * new renderbuffer. It might be that there is a window system * renderbuffer available. */ - if (stfb->iface) - stfb->iface_stamp = p_atomic_read(&stfb->iface->stamp) - 1; + if (stfb->drawable) + stfb->drawable_stamp = p_atomic_read(&stfb->drawable->stamp) - 1; - st_invalidate_buffers(st); + st_invalidate_buffers(st_context(ctx)); return true; } @@ -1296,7 +1336,7 @@ get_version(struct pipe_screen *screen, _mesa_init_constants(&consts, api); _mesa_init_extensions(&extensions); - st_init_limits(screen, &consts, &extensions); + st_init_limits(screen, &consts, &extensions, api); st_init_extensions(screen, &consts, &extensions, options, api); version = _mesa_get_version(&extensions, &consts, api); free(consts.SpirVExtensions); @@ -1304,41 +1344,43 @@ get_version(struct pipe_screen *screen, } -static void -st_api_query_versions(struct st_api *stapi, struct st_manager *sm, +/** + * Query supported OpenGL versions. (if applicable) + * The format is (major*10+minor). + */ +void +st_api_query_versions(struct pipe_frontend_screen *fscreen, struct st_config_options *options, int *gl_core_version, int *gl_compat_version, int *gl_es1_version, int *gl_es2_version) { - *gl_core_version = get_version(sm->screen, options, API_OPENGL_CORE); - *gl_compat_version = get_version(sm->screen, options, API_OPENGL_COMPAT); - *gl_es1_version = get_version(sm->screen, options, API_OPENGLES); - *gl_es2_version = get_version(sm->screen, options, API_OPENGLES2); + *gl_core_version = get_version(fscreen->screen, options, API_OPENGL_CORE); + *gl_compat_version = get_version(fscreen->screen, options, API_OPENGL_COMPAT); + *gl_es1_version = get_version(fscreen->screen, options, API_OPENGLES); + *gl_es2_version = get_version(fscreen->screen, options, API_OPENGLES2); } -static const struct st_api st_gl_api = { - .name = "Mesa " PACKAGE_VERSION, - .api = ST_API_OPENGL, - .profile_mask = ST_PROFILE_DEFAULT_MASK | - ST_PROFILE_OPENGL_CORE_MASK | - ST_PROFILE_OPENGL_ES1_MASK | - ST_PROFILE_OPENGL_ES2_MASK | - 0, - .feature_mask = ST_API_FEATURE_MS_VISUALS_MASK, - .destroy = st_api_destroy, - .query_versions = st_api_query_versions, - .create_context = st_api_create_context, - .make_current = st_api_make_current, - .get_current = st_api_get_current, - .destroy_drawable = st_api_destroy_drawable, -}; +void +st_manager_invalidate_drawables(struct gl_context *ctx) +{ + struct gl_framebuffer *stdraw; + struct gl_framebuffer *stread; + /* + * Normally we'd want the frontend manager to mark the drawables + * invalid only when needed. This will force the frontend manager + * to revalidate the drawable, rather than just update the context with + * the latest cached drawable info. + */ -struct st_api * -st_gl_api_create(void) -{ - return (struct st_api *) &st_gl_api; + stdraw = st_ws_framebuffer(ctx->DrawBuffer); + stread = st_ws_framebuffer(ctx->ReadBuffer); + + if (stdraw) + stdraw->drawable_stamp = p_atomic_read(&stdraw->drawable->stamp) - 1; + if (stread && stread != stdraw) + stread->drawable_stamp = p_atomic_read(&stread->drawable->stamp) - 1; } |