X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fstate_tracker%2Fst_cb_flush.c;h=36f7f2320c8ee4770d8dcf939a1328c0a107e721;hb=0c74e354d10b3a7640f682a43ca0984bc93fa3ef;hp=415e8f3d2a2188bd748379e74108c00dc6d23c71;hpb=64644ec3b21884d4a974fa29087fa98c4ed9e112;p=mesa.git diff --git a/src/mesa/state_tracker/st_cb_flush.c b/src/mesa/state_tracker/st_cb_flush.c index 415e8f3d2a2..36f7f2320c8 100644 --- a/src/mesa/state_tracker/st_cb_flush.c +++ b/src/mesa/state_tracker/st_cb_flush.c @@ -1,8 +1,8 @@ /************************************************************************** - * - * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * + * Copyright 2007 VMware, Inc. * All Rights Reserved. - * + * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including @@ -10,24 +10,24 @@ * distribute, sub license, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: - * + * * The above copyright notice and this permission notice (including the * next paragraph) 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, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS 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: - * Keith Whitwell + * Keith Whitwell * Brian Paul */ @@ -39,73 +39,47 @@ #include "st_cb_flush.h" #include "st_cb_clear.h" #include "st_cb_fbo.h" +#include "st_context.h" #include "st_manager.h" #include "pipe/p_context.h" #include "pipe/p_defines.h" #include "pipe/p_screen.h" #include "util/u_gen_mipmap.h" -#include "util/u_blit.h" -/** Check if we have a front color buffer and if it's been drawn to. */ -static INLINE GLboolean -is_front_buffer_dirty(struct st_context *st) +void +st_flush(struct st_context *st, + struct pipe_fence_handle **fence, + unsigned flags) { - GLframebuffer *fb = st->ctx->DrawBuffer; - struct st_renderbuffer *strb - = st_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer); - return strb && strb->defined; -} - - -/** - * Tell the screen to display the front color buffer on-screen. - */ -static void -display_front_buffer(struct st_context *st) -{ - GLframebuffer *fb = st->ctx->DrawBuffer; - struct st_renderbuffer *strb - = st_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer); - - if (strb) { - /* Hook for copying "fake" frontbuffer if necessary: - */ - st_manager_flush_frontbuffer(st); - } -} - + st_flush_bitmap_cache(st); -void st_flush( struct st_context *st, uint pipeFlushFlags, - struct pipe_fence_handle **fence ) -{ - FLUSH_CURRENT(st->ctx, 0); - - /* Release any vertex buffers that might potentially be accessed in - * successive frames: + /* We want to call this function periodically. + * Typically, it has nothing to do so it shouldn't be expensive. */ - st_flush_bitmap(st); - st_flush_clear(st); - util_blit_flush(st->blit); - util_gen_mipmap_flush(st->gen_mipmap); + st_context_free_zombie_objects(st); - st->pipe->flush( st->pipe, pipeFlushFlags, fence ); + st->pipe->flush(st->pipe, fence, flags); } /** * Flush, and wait for completion. */ -void st_finish( struct st_context *st ) +void +st_finish(struct st_context *st) { struct pipe_fence_handle *fence = NULL; - st_flush(st, PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, &fence); + st_flush(st, &fence, PIPE_FLUSH_ASYNC | PIPE_FLUSH_HINT_FINISH); - if(fence) { - st->pipe->screen->fence_finish(st->pipe->screen, fence, 0); + if (fence) { + st->pipe->screen->fence_finish(st->pipe->screen, NULL, fence, + PIPE_TIMEOUT_INFINITE); st->pipe->screen->fence_reference(st->pipe->screen, &fence, NULL); } + + st_manager_flush_swapbuffers(); } @@ -113,52 +87,110 @@ void st_finish( struct st_context *st ) /** * Called via ctx->Driver.Flush() */ -static void st_glFlush(GLcontext *ctx) +static void +st_glFlush(struct gl_context *ctx) { - struct st_context *st = ctx->st; + struct st_context *st = st_context(ctx); /* Don't call st_finish() here. It is not the state tracker's * responsibilty to inject sleeps in the hope of avoiding buffer * synchronization issues. Calling finish() here will just hide * problems that need to be fixed elsewhere. */ - st_flush(st, PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL); + st_flush(st, NULL, 0); - if (is_front_buffer_dirty(st)) { - display_front_buffer(st); - } + st_manager_flush_frontbuffer(st); } /** * Called via ctx->Driver.Finish() */ -static void st_glFinish(GLcontext *ctx) +static void +st_glFinish(struct gl_context *ctx) { - struct st_context *st = ctx->st; + struct st_context *st = st_context(ctx); st_finish(st); - if (is_front_buffer_dirty(st)) { - display_front_buffer(st); + st_manager_flush_frontbuffer(st); +} + + +static GLenum +gl_reset_status_from_pipe_reset_status(enum pipe_reset_status status) +{ + switch (status) { + case PIPE_NO_RESET: + return GL_NO_ERROR; + case PIPE_GUILTY_CONTEXT_RESET: + return GL_GUILTY_CONTEXT_RESET_ARB; + case PIPE_INNOCENT_CONTEXT_RESET: + return GL_INNOCENT_CONTEXT_RESET_ARB; + case PIPE_UNKNOWN_CONTEXT_RESET: + return GL_UNKNOWN_CONTEXT_RESET_ARB; + default: + assert(0); + return GL_NO_ERROR; + } +} + + +static void +st_device_reset_callback(void *data, enum pipe_reset_status status) +{ + struct st_context *st = data; + + assert(status != PIPE_NO_RESET); + + st->reset_status = status; + _mesa_set_context_lost_dispatch(st->ctx); +} + + +/** + * Query information about GPU resets observed by this context + * + * Called via \c dd_function_table::GetGraphicsResetStatus. + */ +static GLenum +st_get_graphics_reset_status(struct gl_context *ctx) +{ + struct st_context *st = st_context(ctx); + enum pipe_reset_status status; + + if (st->reset_status != PIPE_NO_RESET) { + status = st->reset_status; + st->reset_status = PIPE_NO_RESET; + } else { + status = st->pipe->get_device_reset_status(st->pipe); + if (status != PIPE_NO_RESET) + st_device_reset_callback(st, status); + } + + return gl_reset_status_from_pipe_reset_status(status); +} + + +void +st_install_device_reset_callback(struct st_context *st) +{ + if (st->pipe->set_device_reset_callback) { + struct pipe_device_reset_callback cb; + cb.reset = st_device_reset_callback; + cb.data = st; + st->pipe->set_device_reset_callback(st->pipe, &cb); } } -void st_init_flush_functions(struct dd_function_table *functions) +void +st_init_flush_functions(struct pipe_screen *screen, + struct dd_function_table *functions) { functions->Flush = st_glFlush; functions->Finish = st_glFinish; - /* Windows opengl32.dll calls glFinish prior to every swapbuffers. - * This is unnecessary and degrades performance. Luckily we have some - * scope to work around this, as the externally-visible behaviour of - * Finish() is identical to Flush() in all cases - no differences in - * rendering or ReadPixels are visible if we opt not to wait here. - * - * Only set this up on windows to avoid suprise elsewhere. - */ -#ifdef PIPE_OS_WINDOWS - functions->Finish = st_glFlush; -#endif + if (screen->get_param(screen, PIPE_CAP_DEVICE_RESET_STATUS_QUERY)) + functions->GetGraphicsResetStatus = st_get_graphics_reset_status; }