X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fstate_tracker%2Fst_manager.c;h=a68544ddac759f270c2d2d5ed31a6b9f723b299d;hb=a22aba4eae9b29db731487bce90e8292f7e82c72;hp=ab86ed5513ac5e3dca62288bf63365d37a6267cd;hpb=262961ef694d90fd008041c8384014fd7ed45594;p=mesa.git diff --git a/src/mesa/state_tracker/st_manager.c b/src/mesa/state_tracker/st_manager.c index ab86ed5513a..a68544ddac7 100644 --- a/src/mesa/state_tracker/st_manager.c +++ b/src/mesa/state_tracker/st_manager.c @@ -14,18 +14,19 @@ * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN - * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. * * Authors: * Chia-I Wu */ -#include "state_tracker/st_api.h" +#include "state_tracker/st_gl_api.h" #include "pipe/p_context.h" #include "pipe/p_screen.h" @@ -33,36 +34,34 @@ #include "util/u_pointer.h" #include "util/u_inlines.h" #include "util/u_atomic.h" +#include "util/u_surface.h" #include "main/mtypes.h" #include "main/context.h" +#include "main/mfeatures.h" #include "main/texobj.h" #include "main/teximage.h" #include "main/texstate.h" -#include "main/texfetch.h" #include "main/framebuffer.h" +#include "main/fbobject.h" #include "main/renderbuffer.h" +#include "main/version.h" #include "st_texture.h" #include "st_context.h" #include "st_format.h" #include "st_cb_fbo.h" +#include "st_cb_flush.h" #include "st_manager.h" -/* these functions are defined in st_context.c */ -struct st_context * -st_create_context(struct pipe_context *pipe, - const __GLcontextModes *visual, - struct st_context *share); -void st_destroy_context(struct st_context *st); -void st_flush(struct st_context *st, uint pipeFlushFlags, - struct pipe_fence_handle **fence); - /** + * Cast wrapper to convert a struct gl_framebuffer to an st_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 st_framebuffer * -st_framebuffer(GLframebuffer *fb) +st_ws_framebuffer(struct gl_framebuffer *fb) { /* FBO cannot be casted. See st_new_framebuffer */ return (struct st_framebuffer *) ((fb && !fb->Name) ? fb : NULL); @@ -145,8 +144,8 @@ buffer_index_to_attachment(gl_buffer_index index) static void st_framebuffer_validate(struct st_framebuffer *stfb, struct st_context *st) { - struct pipe_screen *screen = st->pipe->screen; - struct pipe_texture *textures[ST_ATTACHMENT_COUNT]; + struct pipe_context *pipe = st->pipe; + struct pipe_resource *textures[ST_ATTACHMENT_COUNT]; uint width, height; unsigned i; boolean changed = FALSE; @@ -163,7 +162,7 @@ st_framebuffer_validate(struct st_framebuffer *stfb, struct st_context *st) for (i = 0; i < stfb->num_statts; i++) { struct st_renderbuffer *strb; - struct pipe_surface *ps; + struct pipe_surface *ps, surf_tmpl; gl_buffer_index idx; if (!textures[i]) @@ -171,22 +170,24 @@ st_framebuffer_validate(struct st_framebuffer *stfb, struct st_context *st) idx = attachment_to_buffer_index(stfb->statts[i]); if (idx >= BUFFER_COUNT) { - pipe_texture_reference(&textures[i], NULL); + pipe_resource_reference(&textures[i], NULL); continue; } strb = st_renderbuffer(stfb->Base.Attachment[idx].Renderbuffer); assert(strb); if (strb->texture == textures[i]) { - pipe_texture_reference(&textures[i], NULL); + pipe_resource_reference(&textures[i], NULL); continue; } - ps = screen->get_tex_surface(screen, textures[i], 0, 0, 0, - PIPE_BUFFER_USAGE_GPU_READ | PIPE_BUFFER_USAGE_GPU_WRITE); + memset(&surf_tmpl, 0, sizeof(surf_tmpl)); + u_surface_default_template(&surf_tmpl, textures[i], + PIPE_BIND_RENDER_TARGET); + ps = pipe->create_surface(pipe, textures[i], &surf_tmpl); if (ps) { pipe_surface_reference(&strb->surface, ps); - pipe_texture_reference(&strb->texture, ps->texture); + pipe_resource_reference(&strb->texture, ps->texture); /* ownership transfered */ pipe_surface_reference(&ps, NULL); @@ -199,7 +200,7 @@ st_framebuffer_validate(struct st_framebuffer *stfb, struct st_context *st) height = strb->Base.Height; } - pipe_texture_reference(&textures[i], NULL); + pipe_resource_reference(&textures[i], NULL); } if (changed) { @@ -251,6 +252,9 @@ st_framebuffer_add_renderbuffer(struct st_framebuffer *stfb, int samples; boolean sw; + if (!stfb->iface) + return FALSE; + /* do not distinguish depth/stencil buffers */ if (idx == BUFFER_STENCIL) idx = BUFFER_DEPTH; @@ -295,11 +299,11 @@ st_framebuffer_add_renderbuffer(struct st_framebuffer *stfb, } /** - * Intialize a __GLcontextModes from a visual. + * Intialize a struct gl_config from a visual. */ static void st_visual_to_context_mode(const struct st_visual *visual, - __GLcontextModes *mode) + struct gl_config *mode) { memset(mode, 0, sizeof(*mode)); @@ -330,15 +334,15 @@ st_visual_to_context_mode(const struct st_visual *visual, } if (visual->depth_stencil_format != PIPE_FORMAT_NONE) { - mode->haveDepthBuffer = GL_TRUE; - mode->haveStencilBuffer = GL_TRUE; - mode->depthBits = util_format_get_component_bits(visual->depth_stencil_format, UTIL_FORMAT_COLORSPACE_ZS, 0); mode->stencilBits = util_format_get_component_bits(visual->depth_stencil_format, UTIL_FORMAT_COLORSPACE_ZS, 1); + + mode->haveDepthBuffer = mode->depthBits > 0; + mode->haveStencilBuffer = mode->stencilBits > 0; } if (visual->accum_format != PIPE_FORMAT_NONE) { @@ -419,9 +423,12 @@ static struct st_framebuffer * st_framebuffer_create(struct st_framebuffer_iface *stfbi) { struct st_framebuffer *stfb; - __GLcontextModes mode; + struct gl_config mode; gl_buffer_index idx; + if (!stfbi) + return NULL; + stfb = CALLOC_STRUCT(st_framebuffer); if (!stfb) return NULL; @@ -461,8 +468,8 @@ static void st_framebuffer_reference(struct st_framebuffer **ptr, struct st_framebuffer *stfb) { - GLframebuffer *fb = &stfb->Base; - _mesa_reference_framebuffer((GLframebuffer **) ptr, fb); + struct gl_framebuffer *fb = &stfb->Base; + _mesa_reference_framebuffer((struct gl_framebuffer **) ptr, fb); } static void @@ -473,12 +480,21 @@ st_context_notify_invalid_framebuffer(struct st_context_iface *stctxi, struct st_framebuffer *stfb; /* either draw or read winsys fb */ - stfb = st_framebuffer(st->ctx->WinSysDrawBuffer); + stfb = st_ws_framebuffer(st->ctx->WinSysDrawBuffer); if (!stfb || stfb->iface != stfbi) - stfb = st_framebuffer(st->ctx->WinSysReadBuffer); - assert(stfb && stfb->iface == stfbi); + stfb = st_ws_framebuffer(st->ctx->WinSysReadBuffer); - p_atomic_set(&stfb->revalidate, TRUE); + if (stfb && stfb->iface == stfbi) { + p_atomic_set(&stfb->revalidate, TRUE); + } + else { + /* This function is probably getting called when we've detected a + * change in a window's size but the currently bound context is + * not bound to that window. + * If the st_framebuffer_iface structure had a pointer to the + * corresponding st_framebuffer we'd be able to handle this. + */ + } } static void @@ -486,24 +502,26 @@ st_context_flush(struct st_context_iface *stctxi, unsigned flags, struct pipe_fence_handle **fence) { struct st_context *st = (struct st_context *) stctxi; - st_flush(st, flags, fence); - if (flags & PIPE_FLUSH_RENDER_CACHE) + st_flush(st, fence); + if (flags & ST_FLUSH_FRONT) st_manager_flush_frontbuffer(st); } static boolean -st_context_teximage(struct st_context_iface *stctxi, enum st_texture_type target, +st_context_teximage(struct st_context_iface *stctxi, + enum st_texture_type target, int level, enum pipe_format internal_format, - struct pipe_texture *tex, boolean mipmap) + struct pipe_resource *tex, boolean mipmap) { struct st_context *st = (struct st_context *) stctxi; - GLcontext *ctx = st->ctx; + struct gl_context *ctx = st->ctx; struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(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; switch (target) { case ST_TEXTURE_1D: @@ -523,12 +541,6 @@ st_context_teximage(struct st_context_iface *stctxi, enum st_texture_type target break; } - if (util_format_get_component_bits(internal_format, - UTIL_FORMAT_COLORSPACE_RGB, 3) > 0) - internalFormat = GL_RGBA; - else - internalFormat = GL_RGB; - texObj = _mesa_select_tex_object(ctx, texUnit, target); _mesa_lock_texture(ctx, texObj); @@ -542,18 +554,57 @@ st_context_teximage(struct st_context_iface *stctxi, enum st_texture_type target texImage = _mesa_get_tex_image(ctx, texObj, target, level); stImage = st_texture_image(texImage); if (tex) { + gl_format texFormat; + + /* + * XXX When internal_format and tex->format differ, st_finalize_texture + * needs to allocate a new texture with internal_format and copy the + * texture here into the new one. It will result in surface_copy being + * called on surfaces whose formats differ. + * + * To avoid that, internal_format is (wrongly) ignored here. A sane fix + * is to use a sampler view. + */ + if (!st_sampler_compat_formats(tex->format, internal_format)) + internal_format = tex->format; + + if (util_format_get_component_bits(internal_format, + UTIL_FORMAT_COLORSPACE_RGB, 3) > 0) + internalFormat = GL_RGBA; + else + internalFormat = GL_RGB; + + texFormat = st_ChooseTextureFormat(ctx, internalFormat, + GL_RGBA, GL_UNSIGNED_BYTE); + _mesa_init_teximage_fields(ctx, target, texImage, - tex->width0, tex->height0, 1, 0, internalFormat); - texImage->TexFormat = st_ChooseTextureFormat(ctx, internalFormat, - GL_RGBA, GL_UNSIGNED_BYTE); - _mesa_set_fetch_functions(texImage, 2); + tex->width0, tex->height0, 1, 0, + internalFormat, texFormat); + + width = tex->width0; + height = tex->height0; + depth = tex->depth0; + + /* grow the image size until we hit level = 0 */ + while (level > 0) { + if (width != 1) + width <<= 1; + if (height != 1) + height <<= 1; + if (depth != 1) + depth <<= 1; + level--; + } } else { _mesa_clear_texture_image(ctx, texImage); + width = height = depth = 0; } - stObj->pipe = st->pipe; - pipe_texture_reference(&stImage->pt, tex); + pipe_resource_reference(&stImage->pt, tex); + stObj->width0 = width; + stObj->height0 = height; + stObj->depth0 = depth; _mesa_dirty_texobj(ctx, texObj, GL_TRUE); _mesa_unlock_texture(ctx, texObj); @@ -561,6 +612,26 @@ st_context_teximage(struct st_context_iface *stctxi, enum st_texture_type target 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 boolean +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) { @@ -570,34 +641,67 @@ st_context_destroy(struct st_context_iface *stctxi) static struct st_context_iface * st_api_create_context(struct st_api *stapi, struct st_manager *smapi, - const struct st_visual *visual, + const struct st_context_attribs *attribs, struct st_context_iface *shared_stctxi) { struct st_context *shared_ctx = (struct st_context *) shared_stctxi; struct st_context *st; struct pipe_context *pipe; - __GLcontextModes mode; + struct gl_config mode; + gl_api api; + + if (!(stapi->profile_mask & (1 << attribs->profile))) + return NULL; + + switch (attribs->profile) { + case ST_PROFILE_DEFAULT: + api = API_OPENGL; + break; + case ST_PROFILE_OPENGL_ES1: + api = API_OPENGLES; + break; + case ST_PROFILE_OPENGL_ES2: + api = API_OPENGLES2; + break; + case ST_PROFILE_OPENGL_CORE: + default: + return NULL; + break; + } pipe = smapi->screen->context_create(smapi->screen, NULL); if (!pipe) return NULL; - st_visual_to_context_mode(visual, &mode); - st = st_create_context(pipe, &mode, shared_ctx); + st_visual_to_context_mode(&attribs->visual, &mode); + st = st_create_context(api, pipe, &mode, shared_ctx); if (!st) { pipe->destroy(pipe); return NULL; } - st->iface.destroy = st_context_destroy; + /* need to perform version check */ + if (attribs->major > 1 || attribs->minor > 0) { + _mesa_compute_version(st->ctx); + /* is the actual version less than the requested version? */ + if (st->ctx->VersionMajor * 10 + st->ctx->VersionMinor < + attribs->major * 10 + attribs->minor) { + st_destroy_context(st); + return NULL; + } + } + + st->invalidate_on_gl_viewport = + smapi->get_param(smapi, ST_MANAGER_BROKEN_INVALIDATE); + + st->iface.destroy = st_context_destroy; st->iface.notify_invalid_framebuffer = st_context_notify_invalid_framebuffer; st->iface.flush = st_context_flush; - st->iface.teximage = st_context_teximage; - st->iface.copy = NULL; - + st->iface.copy = st_context_copy; + st->iface.share = st_context_share; st->iface.st_context_private = (void *) smapi; return &st->iface; @@ -616,7 +720,7 @@ st_api_make_current(struct st_api *stapi, struct st_context_iface *stctxi, if (st) { /* reuse/create the draw fb */ - stfb = st_framebuffer(st->ctx->WinSysDrawBuffer); + stfb = st_ws_framebuffer(st->ctx->WinSysDrawBuffer); if (stfb && stfb->iface == stdrawi) { stdraw = NULL; st_framebuffer_reference(&stdraw, stfb); @@ -626,7 +730,7 @@ st_api_make_current(struct st_api *stapi, struct st_context_iface *stctxi, } /* reuse/create the read fb */ - stfb = st_framebuffer(st->ctx->WinSysReadBuffer); + stfb = st_ws_framebuffer(st->ctx->WinSysReadBuffer); if (!stfb || stfb->iface != streadi) stfb = stdraw; if (stfb && stfb->iface == streadi) { @@ -643,15 +747,20 @@ st_api_make_current(struct st_api *stapi, struct st_context_iface *stctxi, st_framebuffer_validate(stread, st); /* modify the draw/read buffers of the context */ - st_visual_to_default_buffer(stdraw->iface->visual, - &st->ctx->Color.DrawBuffer[0], NULL); - st_visual_to_default_buffer(stread->iface->visual, - &st->ctx->Pixel.ReadBuffer, NULL); + if (stdraw->iface) { + st_visual_to_default_buffer(stdraw->iface->visual, + &st->ctx->Color.DrawBuffer[0], NULL); + } + if (stread->iface) { + st_visual_to_default_buffer(stread->iface->visual, + &st->ctx->Pixel.ReadBuffer, NULL); + } ret = _mesa_make_current(st->ctx, &stdraw->Base, &stread->Base); } else { - ret = FALSE; + struct gl_framebuffer *incomplete = _mesa_get_incomplete_framebuffer(); + ret = _mesa_make_current(st->ctx, incomplete, incomplete); } st_framebuffer_reference(&stdraw, NULL); @@ -673,13 +782,6 @@ st_api_get_current(struct st_api *stapi) return (st) ? &st->iface : NULL; } -static boolean -st_api_is_visual_supported(struct st_api *stapi, - const struct st_visual *visual) -{ - return TRUE; -} - static st_proc_t st_api_get_proc_address(struct st_api *stapi, const char *procname) { @@ -689,7 +791,6 @@ st_api_get_proc_address(struct st_api *stapi, const char *procname) static void st_api_destroy(struct st_api *stapi) { - FREE(stapi); } /** @@ -698,7 +799,7 @@ st_api_destroy(struct st_api *stapi) void st_manager_flush_frontbuffer(struct st_context *st) { - struct st_framebuffer *stfb = st_framebuffer(st->ctx->DrawBuffer); + struct st_framebuffer *stfb = st_ws_framebuffer(st->ctx->DrawBuffer); struct st_renderbuffer *strb = NULL; if (stfb) @@ -706,33 +807,51 @@ st_manager_flush_frontbuffer(struct st_context *st) if (!strb) return; - /* st_public.h */ - if (!stfb->iface) { - struct pipe_surface *front_surf = strb->surface; - st->pipe->screen->flush_frontbuffer(st->pipe->screen, - front_surf, st->winsys_drawable_handle); - return; - } - + /* never a dummy fb */ + assert(stfb->iface); stfb->iface->flush_front(stfb->iface, ST_ATTACHMENT_FRONT_LEFT); } +/** + * Return the surface of an EGLImage. + * FIXME: I think this should operate on resources, not surfaces + */ +struct pipe_surface * +st_manager_get_egl_image_surface(struct st_context *st, + void *eglimg, unsigned usage) +{ + struct st_manager *smapi = + (struct st_manager *) st->iface.st_context_private; + struct st_egl_image stimg; + struct pipe_surface *ps, surf_tmpl; + + if (!smapi || !smapi->get_egl_image) + return NULL; + + memset(&stimg, 0, sizeof(stimg)); + if (!smapi->get_egl_image(smapi, eglimg, &stimg)) + return NULL; + + memset(&surf_tmpl, 0, sizeof(surf_tmpl)); + surf_tmpl.format = stimg.texture->format; + surf_tmpl.usage = usage; + surf_tmpl.u.tex.level = stimg.level; + surf_tmpl.u.tex.first_layer = stimg.layer; + surf_tmpl.u.tex.last_layer = stimg.layer; + ps = st->pipe->create_surface(st->pipe, stimg.texture, &surf_tmpl); + pipe_resource_reference(&stimg.texture, NULL); + + return ps; +} + /** * Re-validate the framebuffers. */ void st_manager_validate_framebuffers(struct st_context *st) { - struct st_framebuffer *stdraw = st_framebuffer(st->ctx->DrawBuffer); - struct st_framebuffer *stread = st_framebuffer(st->ctx->ReadBuffer); - - /* st_public.h */ - if ((stdraw && !stdraw->iface) || (stread && !stread->iface)) { - struct pipe_screen *screen = st->pipe->screen; - if (screen->update_buffer) - screen->update_buffer(screen, st->pipe->priv); - return; - } + struct st_framebuffer *stdraw = st_ws_framebuffer(st->ctx->DrawBuffer); + struct st_framebuffer *stread = st_ws_framebuffer(st->ctx->ReadBuffer); if (stdraw) st_framebuffer_validate(stdraw, st); @@ -744,13 +863,14 @@ st_manager_validate_framebuffers(struct st_context *st) * Add a color renderbuffer on demand. */ boolean -st_manager_add_color_renderbuffer(struct st_context *st, GLframebuffer *fb, +st_manager_add_color_renderbuffer(struct st_context *st, + struct gl_framebuffer *fb, gl_buffer_index idx) { - struct st_framebuffer *stfb = st_framebuffer(fb); + struct st_framebuffer *stfb = st_ws_framebuffer(fb); - /* FBO or st_public.h */ - if (!stfb || !stfb->iface) + /* FBO */ + if (!stfb) return FALSE; if (stfb->Base.Attachment[idx].Renderbuffer) @@ -776,24 +896,28 @@ st_manager_add_color_renderbuffer(struct st_context *st, GLframebuffer *fb, return TRUE; } -/** - * Create an st_api to manage the state tracker. - */ +static const struct st_api st_gl_api = { + "Mesa " MESA_VERSION_STRING, + ST_API_OPENGL, +#if FEATURE_GL + ST_PROFILE_DEFAULT_MASK | +#endif +#if FEATURE_ES1 + ST_PROFILE_OPENGL_ES1_MASK | +#endif +#if FEATURE_ES2 + ST_PROFILE_OPENGL_ES2_MASK | +#endif + 0, + st_api_destroy, + st_api_get_proc_address, + st_api_create_context, + st_api_make_current, + st_api_get_current, +}; + struct st_api * -st_manager_create_api(void) +st_gl_api_create(void) { - struct st_api *stapi; - - stapi = CALLOC_STRUCT(st_api); - if (stapi) { - stapi->destroy = st_api_destroy; - stapi->get_proc_address = st_api_get_proc_address; - stapi->is_visual_supported = st_api_is_visual_supported; - - stapi->create_context = st_api_create_context; - stapi->make_current = st_api_make_current; - stapi->get_current = st_api_get_current; - } - - return stapi; + return (struct st_api *) &st_gl_api; }