llvmpipe: Ensure the context is flushed before modifying textures.

This commit is contained in:
José Fonseca 2010-03-13 16:13:26 +00:00
parent 3abc7b985c
commit bf40c34663
4 changed files with 102 additions and 0 deletions

View File

@ -92,3 +92,68 @@ llvmpipe_flush( struct pipe_context *pipe,
#endif
}
/**
* Flush context if necessary.
*
* TODO: move this logic to an auxiliary library?
*
* FIXME: We must implement DISCARD/DONTBLOCK/UNSYNCHRONIZED/etc for
* textures to avoid blocking.
*/
boolean
llvmpipe_flush_texture(struct pipe_context *pipe,
struct pipe_texture *texture,
unsigned face,
unsigned level,
unsigned flush_flags,
boolean read_only,
boolean cpu_access,
boolean do_not_flush)
{
struct pipe_fence_handle *last_fence = NULL;
unsigned referenced;
referenced = pipe->is_texture_referenced(pipe, texture, face, level);
if ((referenced & PIPE_REFERENCED_FOR_WRITE) ||
((referenced & PIPE_REFERENCED_FOR_READ) && !read_only)) {
if (do_not_flush)
return FALSE;
/*
* TODO: The semantics of these flush flags are too obtuse. They should
* disappear and the pipe driver should just ensure that all visible
* side-effects happen when they need to happen.
*/
if (referenced & PIPE_REFERENCED_FOR_WRITE)
flush_flags |= PIPE_FLUSH_RENDER_CACHE;
if (referenced & PIPE_REFERENCED_FOR_READ)
flush_flags |= PIPE_FLUSH_TEXTURE_CACHE;
if (cpu_access) {
/*
* Flush and wait.
*/
struct pipe_fence_handle *fence = NULL;
pipe->flush(pipe, flush_flags, &fence);
if (last_fence) {
pipe->screen->fence_finish(pipe->screen, fence, 0);
pipe->screen->fence_reference(pipe->screen, &fence, NULL);
}
} else {
/*
* Just flush.
*/
pipe->flush(pipe, flush_flags, NULL);
}
}
return TRUE;
}

View File

@ -28,10 +28,22 @@
#ifndef LP_FLUSH_H
#define LP_FLUSH_H
#include "pipe/p_compiler.h"
struct pipe_context;
struct pipe_fence_handle;
void llvmpipe_flush(struct pipe_context *pipe, unsigned flags,
struct pipe_fence_handle **fence);
boolean
llvmpipe_flush_texture(struct pipe_context *pipe,
struct pipe_texture *texture,
unsigned face,
unsigned level,
unsigned flush_flags,
boolean read_only,
boolean cpu_access,
boolean do_not_flush);
#endif

View File

@ -27,6 +27,7 @@
#include "util/u_rect.h"
#include "lp_context.h"
#include "lp_flush.h"
#include "lp_surface.h"
@ -36,6 +37,20 @@ lp_surface_copy(struct pipe_context *pipe,
struct pipe_surface *src, unsigned srcx, unsigned srcy,
unsigned width, unsigned height)
{
llvmpipe_flush_texture(pipe,
dest->texture, dest->face, dest->level,
0, /* flush_flags */
FALSE, /* read_only */
FALSE, /* cpu_access */
FALSE); /* do_not_flush */
llvmpipe_flush_texture(pipe,
src->texture, src->face, src->level,
0, /* flush_flags */
TRUE, /* read_only */
FALSE, /* cpu_access */
FALSE); /* do_not_flush */
util_surface_copy(pipe, FALSE,
dest, destx, desty,
src, srcx, srcy,

View File

@ -371,6 +371,16 @@ llvmpipe_transfer_map( struct pipe_context *pipe,
lpt = llvmpipe_texture(transfer->texture);
format = lpt->base.format;
/*
* Transfers, like other pipe operations, must happen in order, so flush the
* context if necessary.
*/
llvmpipe_flush_texture(pipe,
transfer->texture, transfer->face, transfer->level,
0, /* flush_flags */
!(transfer->usage & PIPE_TRANSFER_WRITE), /* read_only */
TRUE, /* cpu_access */
FALSE); /* do_not_flush */
map = llvmpipe_texture_map(transfer->texture,
transfer->face, transfer->level, transfer->zslice);