--
This fixes the problem on radeon, but it would be good to get some testing
on Nouveau as well. According to Christian, testing nouveau with Kodi should
do the trick, probably mpv --hwdec=vdpau --vo=opengl should also work. Errors
may only be noticeable as bad (de-)interlacing.
---
src/mesa/state_tracker/st_sampler_view.c | 15 +++++++++++----
src/mesa/state_tracker/st_texture.h | 9 +++++++++
src/mesa/state_tracker/st_vdpau.c | 20 +++++++-------------
3 files changed, 27 insertions(+), 17 deletions(-)
diff --git a/src/mesa/state_tracker/st_sampler_view.c
b/src/mesa/state_tracker/st_sampler_view.c
index 9fe0bfe..2b2fa8b 100644
--- a/src/mesa/state_tracker/st_sampler_view.c
+++ b/src/mesa/state_tracker/st_sampler_view.c
@@ -423,22 +423,26 @@ st_create_texture_sampler_view_from_stobj(struct
st_context *st,
size = MIN2(stObj->pt->width0 - base, (unsigned)stObj->base.BufferSize);
if (!size)
return NULL;
templ.u.buf.offset = base;
templ.u.buf.size = size;
} else {
templ.u.tex.first_level = stObj->base.MinLevel + stObj->base.BaseLevel;
templ.u.tex.last_level = last_level(stObj);
assert(templ.u.tex.first_level <= templ.u.tex.last_level);
- templ.u.tex.first_layer = stObj->base.MinLayer;
- templ.u.tex.last_layer = last_layer(stObj);
+ if (stObj->layer_override) {
+ templ.u.tex.first_layer = templ.u.tex.last_layer =
stObj->layer_override;
+ } else {
+ templ.u.tex.first_layer = stObj->base.MinLayer;
+ templ.u.tex.last_layer = last_layer(stObj);
+ }
assert(templ.u.tex.first_layer <= templ.u.tex.last_layer);
templ.target = gl_target_to_pipe(stObj->base.Target);
}
templ.swizzle_r = GET_SWZ(swizzle, 0);
templ.swizzle_g = GET_SWZ(swizzle, 1);
templ.swizzle_b = GET_SWZ(swizzle, 2);
templ.swizzle_a = GET_SWZ(swizzle, 3);
return st->pipe->create_sampler_view(st->pipe, stObj->pt, &templ);
@@ -471,22 +475,25 @@ st_get_texture_sampler_view_from_stobj(struct st_context
*st,
unsigned base = stObj->base.BufferOffset;
unsigned size = MIN2(stObj->pt->width0 - base,
(unsigned) stObj->base.BufferSize);
assert(view->u.buf.offset == base);
assert(view->u.buf.size == size);
}
else {
assert(stObj->base.MinLevel + stObj->base.BaseLevel ==
view->u.tex.first_level);
assert(last_level(stObj) == view->u.tex.last_level);
- assert(stObj->base.MinLayer == view->u.tex.first_layer);
- assert(last_layer(stObj) == view->u.tex.last_layer);
+ assert(stObj->layer_override || stObj->base.MinLayer ==
view->u.tex.first_layer);
+ assert(stObj->layer_override || last_layer(stObj) ==
view->u.tex.last_layer);
+ assert(!stObj->layer_override ||
+ (stObj->layer_override == view->u.tex.first_layer &&
+ stObj->layer_override == view->u.tex.last_layer));
}
}
else {
/* create new sampler view */
enum pipe_format format = get_sampler_view_format(st, stObj, samp);
*sv = st_create_texture_sampler_view_from_stobj(st, stObj,
format, glsl_version);
}
diff --git a/src/mesa/state_tracker/st_texture.h
b/src/mesa/state_tracker/st_texture.h
index 730843a..0ce7989 100644
--- a/src/mesa/state_tracker/st_texture.h
+++ b/src/mesa/state_tracker/st_texture.h
@@ -101,20 +101,29 @@ struct st_texture_object
* cannot be reallocated and the format can only be changed with a sampler
* view or a surface.
*/
GLboolean surface_based;
/* If surface_based is true, this format should be used for all sampler
* views and surfaces instead of pt->format.
*/
enum pipe_format surface_format;
+ /* When non-zero, samplers should use this layer instead of the one
+ * specified by the GL state.
+ *
+ * This is used for VDPAU interop, where imported pipe_resources may be
+ * array textures (containing layers with different fields) even though the
+ * GL state describes one non-array texture per field.
+ */
+ uint layer_override;
+
/** The glsl version of the shader seen during the previous validation */
unsigned prev_glsl_version;
/** The value of the sampler's sRGBDecode state at the previous validation
*/
GLenum prev_sRGBDecode;
};
static inline struct st_texture_image *
st_texture_image(struct gl_texture_image *img)
{
diff --git a/src/mesa/state_tracker/st_vdpau.c
b/src/mesa/state_tracker/st_vdpau.c
index 7912057..0273815 100644
--- a/src/mesa/state_tracker/st_vdpau.c
+++ b/src/mesa/state_tracker/st_vdpau.c
@@ -182,34 +182,36 @@ static void
st_vdpau_map_surface(struct gl_context *ctx, GLenum target, GLenum access,
GLboolean output, struct gl_texture_object *texObj,
struct gl_texture_image *texImage,
const void *vdpSurface, GLuint index)
{
struct st_context *st = st_context(ctx);
struct st_texture_object *stObj = st_texture_object(texObj);
struct st_texture_image *stImage = st_texture_image(texImage);
struct pipe_resource *res;
- struct pipe_sampler_view templ, **sampler_view;
mesa_format texFormat;
+ uint layer_override = 0;
if (output) {
res = st_vdpau_output_surface_dma_buf(ctx, vdpSurface);
if (!res)
res = st_vdpau_output_surface_gallium(ctx, vdpSurface);
} else {
res = st_vdpau_video_surface_dma_buf(ctx, vdpSurface, index);
- if (!res)
+ if (!res) {
res = st_vdpau_video_surface_gallium(ctx, vdpSurface, index);
+ layer_override = index & 1;
+ }
}
if (!res) {
_mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUMapSurfacesNV");
return;
}
/* do we have different screen objects ? */
if (res->screen != st->pipe->screen) {
_mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUMapSurfacesNV");
@@ -226,51 +228,43 @@ st_vdpau_map_surface(struct gl_context *ctx, GLenum
target, GLenum access,
texFormat = st_pipe_format_to_mesa_format(res->format);
_mesa_init_teximage_fields(ctx, texImage,
res->width0, res->height0, 1, 0, GL_RGBA,
texFormat);
pipe_resource_reference(&stObj->pt, res);
st_texture_release_all_sampler_views(st, stObj);
pipe_resource_reference(&stImage->pt, res);
- u_sampler_view_default_template(&templ, res, res->format);
- templ.u.tex.first_layer = index & 1;
- templ.u.tex.last_layer = index & 1;
- templ.swizzle_r = GET_SWZ(stObj->base._Swizzle, 0);
- templ.swizzle_g = GET_SWZ(stObj->base._Swizzle, 1);
- templ.swizzle_b = GET_SWZ(stObj->base._Swizzle, 2);
- templ.swizzle_a = GET_SWZ(stObj->base._Swizzle, 3);
-
- sampler_view = st_texture_get_sampler_view(st, stObj);
- *sampler_view = st->pipe->create_sampler_view(st->pipe, res, &templ);
-
stObj->surface_format = res->format;
+ stObj->layer_override = layer_override;
_mesa_dirty_texobj(ctx, texObj);
pipe_resource_reference(&res, NULL);
}
static void
st_vdpau_unmap_surface(struct gl_context *ctx, GLenum target, GLenum access,
GLboolean output, struct gl_texture_object *texObj,
struct gl_texture_image *texImage,
const void *vdpSurface, GLuint index)
{
struct st_context *st = st_context(ctx);
struct st_texture_object *stObj = st_texture_object(texObj);
struct st_texture_image *stImage = st_texture_image(texImage);
pipe_resource_reference(&stObj->pt, NULL);
st_texture_release_all_sampler_views(st, stObj);
pipe_resource_reference(&stImage->pt, NULL);
+ stObj->layer_override = 0;
+
_mesa_dirty_texobj(ctx, texObj);
st_flush(st, NULL, 0);
}
#endif
void
st_init_vdpau_functions(struct dd_function_table *functions)
{