mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-07 02:48:06 +02:00
st/xorg: add yuv vertex shader
plus some general fixes
This commit is contained in:
parent
6b8ce4cc4f
commit
a9f8baf00b
5 changed files with 200 additions and 33 deletions
|
|
@ -236,6 +236,7 @@ create_vs(struct pipe_context *pipe,
|
||||||
boolean is_fill = vs_traits & VS_FILL;
|
boolean is_fill = vs_traits & VS_FILL;
|
||||||
boolean is_composite = vs_traits & VS_COMPOSITE;
|
boolean is_composite = vs_traits & VS_COMPOSITE;
|
||||||
boolean has_mask = vs_traits & VS_MASK;
|
boolean has_mask = vs_traits & VS_MASK;
|
||||||
|
boolean is_yuv = vs_traits & VS_YUV;
|
||||||
unsigned input_slot = 0;
|
unsigned input_slot = 0;
|
||||||
|
|
||||||
ureg = ureg_create(TGSI_PROCESSOR_VERTEX);
|
ureg = ureg_create(TGSI_PROCESSOR_VERTEX);
|
||||||
|
|
@ -254,6 +255,20 @@ create_vs(struct pipe_context *pipe,
|
||||||
const0, const1);
|
const0, const1);
|
||||||
ureg_MOV(ureg, dst, src);
|
ureg_MOV(ureg, dst, src);
|
||||||
|
|
||||||
|
if (is_yuv) {
|
||||||
|
src = ureg_DECL_vs_input(ureg, input_slot++);
|
||||||
|
dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 0);
|
||||||
|
ureg_MOV(ureg, dst, src);
|
||||||
|
|
||||||
|
src = ureg_DECL_vs_input(ureg, input_slot++);
|
||||||
|
dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 1);
|
||||||
|
ureg_MOV(ureg, dst, src);
|
||||||
|
|
||||||
|
src = ureg_DECL_vs_input(ureg, input_slot++);
|
||||||
|
dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 2);
|
||||||
|
ureg_MOV(ureg, dst, src);
|
||||||
|
}
|
||||||
|
|
||||||
if (is_composite) {
|
if (is_composite) {
|
||||||
src = ureg_DECL_vs_input(ureg, input_slot++);
|
src = ureg_DECL_vs_input(ureg, input_slot++);
|
||||||
dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 0);
|
dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 0);
|
||||||
|
|
|
||||||
|
|
@ -9,10 +9,12 @@ enum xorg_vs_traits {
|
||||||
VS_SOLID_FILL = 1 << 2,
|
VS_SOLID_FILL = 1 << 2,
|
||||||
VS_LINGRAD_FILL = 1 << 3,
|
VS_LINGRAD_FILL = 1 << 3,
|
||||||
VS_RADGRAD_FILL = 1 << 4,
|
VS_RADGRAD_FILL = 1 << 4,
|
||||||
|
VS_YUV = 1 << 5,
|
||||||
|
|
||||||
|
|
||||||
VS_FILL = (VS_SOLID_FILL |
|
VS_FILL = (VS_SOLID_FILL |
|
||||||
VS_LINGRAD_FILL |
|
VS_LINGRAD_FILL |
|
||||||
VS_RADGRAD_FILL)
|
VS_RADGRAD_FILL)
|
||||||
/*VS_TRANSFORM = 1 << 5*/
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum xorg_fs_traits {
|
enum xorg_fs_traits {
|
||||||
|
|
|
||||||
|
|
@ -224,6 +224,44 @@ setup_vertex_data2(struct xorg_renderer *r,
|
||||||
sizeof(r->vertices3));
|
sizeof(r->vertices3));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct pipe_buffer *
|
||||||
|
setup_vertex_data_yuv(struct xorg_renderer *r,
|
||||||
|
float srcX, float srcY,
|
||||||
|
float dstX, float dstY,
|
||||||
|
float width, float height,
|
||||||
|
struct pipe_texture **tex)
|
||||||
|
{
|
||||||
|
float s0, t0, s1, t1;
|
||||||
|
float spt0[2], spt1[2];
|
||||||
|
|
||||||
|
spt0[0] = srcX;
|
||||||
|
spt0[1] = srcY;
|
||||||
|
spt1[0] = srcX + width;
|
||||||
|
spt1[1] = srcY + height;
|
||||||
|
|
||||||
|
s0 = spt0[0] / tex[0]->width[0];
|
||||||
|
t0 = spt0[1] / tex[0]->height[0];
|
||||||
|
s1 = spt1[0] / tex[0]->width[0];
|
||||||
|
t1 = spt1[1] / tex[0]->height[0];
|
||||||
|
|
||||||
|
/* 1st vertex */
|
||||||
|
setup_vertex1(r->vertices2[0], dstX, dstY, s0, t0);
|
||||||
|
/* 2nd vertex */
|
||||||
|
setup_vertex1(r->vertices2[1], dstX + width, dstY,
|
||||||
|
s1, t0);
|
||||||
|
/* 3rd vertex */
|
||||||
|
setup_vertex1(r->vertices2[2], dstX + width, dstY + height,
|
||||||
|
s1, t1);
|
||||||
|
/* 4th vertex */
|
||||||
|
setup_vertex1(r->vertices2[3], dstX, dstY + height,
|
||||||
|
s0, t1);
|
||||||
|
|
||||||
|
|
||||||
|
return pipe_user_buffer_create(r->pipe->screen,
|
||||||
|
r->vertices2,
|
||||||
|
sizeof(r->vertices2));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -825,6 +863,13 @@ void renderer_draw_textures(struct xorg_renderer *r,
|
||||||
textures[0], textures[1],
|
textures[0], textures[1],
|
||||||
src_matrix, mask_matrix);
|
src_matrix, mask_matrix);
|
||||||
break;
|
break;
|
||||||
|
case 3:
|
||||||
|
buf = setup_vertex_data_yuv(r,
|
||||||
|
pos[0], pos[1],
|
||||||
|
pos[2], pos[3],
|
||||||
|
width, height,
|
||||||
|
textures);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
debug_assert(!"Unsupported number of textures");
|
debug_assert(!"Unsupported number of textures");
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ struct xorg_renderer {
|
||||||
struct pipe_constant_buffer vs_const_buffer;
|
struct pipe_constant_buffer vs_const_buffer;
|
||||||
struct pipe_constant_buffer fs_const_buffer;
|
struct pipe_constant_buffer fs_const_buffer;
|
||||||
|
|
||||||
/* we should combine these two */
|
/* we should combine these three */
|
||||||
float vertices2[4][2][4];
|
float vertices2[4][2][4];
|
||||||
float vertices3[4][3][4];
|
float vertices3[4][3][4];
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,9 @@
|
||||||
|
|
||||||
#include "xorg_exa.h"
|
#include "xorg_exa.h"
|
||||||
#include "xorg_renderer.h"
|
#include "xorg_renderer.h"
|
||||||
|
#include "xorg_exa_tgsi.h"
|
||||||
|
|
||||||
|
#include "cso_cache/cso_context.h"
|
||||||
|
|
||||||
#include "pipe/p_screen.h"
|
#include "pipe/p_screen.h"
|
||||||
#include "pipe/p_inlines.h"
|
#include "pipe/p_inlines.h"
|
||||||
|
|
@ -280,43 +283,144 @@ copy_packed_data(ScrnInfoPtr pScrn,
|
||||||
screen->tex_transfer_destroy(vtrans);
|
screen->tex_transfer_destroy(vtrans);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
setup_video_constants(struct xorg_renderer *r, boolean hdtv)
|
setup_vs_video_constants(struct xorg_renderer *r, struct exa_pixmap_priv *dst)
|
||||||
|
{
|
||||||
|
int width = dst->tex->width[0];
|
||||||
|
int height = dst->tex->height[0];
|
||||||
|
const int param_bytes = 8 * sizeof(float);
|
||||||
|
float vs_consts[8] = {
|
||||||
|
2.f/width, 2.f/height, 1, 1,
|
||||||
|
-1, -1, 0, 0
|
||||||
|
};
|
||||||
|
|
||||||
|
renderer_set_constants(r, PIPE_SHADER_VERTEX,
|
||||||
|
vs_consts, param_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
setup_fs_video_constants(struct xorg_renderer *r, boolean hdtv)
|
||||||
{
|
{
|
||||||
struct pipe_context *pipe = r->pipe;
|
|
||||||
const int param_bytes = 12 * sizeof(float);
|
const int param_bytes = 12 * sizeof(float);
|
||||||
struct pipe_constant_buffer *cbuf = &r->fs_const_buffer;
|
const float *video_constants = (hdtv) ? bt_709 : bt_601;
|
||||||
|
|
||||||
pipe_buffer_reference(&cbuf->buffer, NULL);
|
renderer_set_constants(r, PIPE_SHADER_FRAGMENT,
|
||||||
cbuf->buffer = pipe_buffer_create(pipe->screen, 16,
|
video_constants, param_bytes);
|
||||||
PIPE_BUFFER_USAGE_CONSTANT,
|
}
|
||||||
param_bytes);
|
|
||||||
|
|
||||||
if (cbuf->buffer) {
|
static void
|
||||||
const float *video_constants = (hdtv) ? bt_709 : bt_601;
|
draw_yuv(struct xorg_xv_port_priv *port, int src_x, int src_y,
|
||||||
|
int dst_x, int dst_y,
|
||||||
|
int w, int h)
|
||||||
|
{
|
||||||
|
int pos[4] = {src_x, src_y,
|
||||||
|
dst_x, dst_y};
|
||||||
|
struct pipe_texture **textures = port->yuv[port->current_set];
|
||||||
|
|
||||||
pipe_buffer_write(pipe->screen, cbuf->buffer,
|
renderer_draw_textures(port->r,
|
||||||
0, param_bytes, video_constants);
|
pos, w, h,
|
||||||
|
textures,
|
||||||
|
3, /*bound samplers/textures */
|
||||||
|
NULL, NULL /* no transformations */);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
bind_blend_state(struct xorg_xv_port_priv *port)
|
||||||
|
{
|
||||||
|
struct pipe_blend_state blend;
|
||||||
|
|
||||||
|
memset(&blend, 0, sizeof(struct pipe_blend_state));
|
||||||
|
blend.blend_enable = 1;
|
||||||
|
blend.colormask |= PIPE_MASK_RGBA;
|
||||||
|
|
||||||
|
/* porter&duff src */
|
||||||
|
blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE;
|
||||||
|
blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE;
|
||||||
|
blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
|
||||||
|
blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
|
||||||
|
|
||||||
|
cso_set_blend(port->r->cso, &blend);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
bind_shaders(struct xorg_xv_port_priv *port)
|
||||||
|
{
|
||||||
|
unsigned vs_traits = 0, fs_traits = 0;
|
||||||
|
struct xorg_shader shader;
|
||||||
|
|
||||||
|
vs_traits |= VS_YUV;
|
||||||
|
fs_traits |= FS_YUV;
|
||||||
|
|
||||||
|
shader = xorg_shaders_get(port->r->shaders, vs_traits, fs_traits);
|
||||||
|
cso_set_vertex_shader_handle(port->r->cso, shader.vs);
|
||||||
|
cso_set_fragment_shader_handle(port->r->cso, shader.fs);
|
||||||
|
}
|
||||||
|
|
||||||
|
static INLINE void
|
||||||
|
conditional_flush(struct pipe_context *pipe, struct pipe_texture **tex,
|
||||||
|
int num)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < num; ++i) {
|
||||||
|
if (tex[i] && pipe->is_texture_referenced(pipe, tex[i], 0, 0) &
|
||||||
|
PIPE_REFERENCED_FOR_WRITE) {
|
||||||
|
pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pipe->set_constant_buffer(pipe, PIPE_SHADER_FRAGMENT, 0, cbuf);
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
bind_samplers(struct xorg_xv_port_priv *port)
|
||||||
|
{
|
||||||
|
struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS];
|
||||||
|
struct pipe_sampler_state sampler;
|
||||||
|
struct pipe_texture **dst = port->yuv[port->current_set];
|
||||||
|
|
||||||
|
memset(&sampler, 0, sizeof(struct pipe_sampler_state));
|
||||||
|
|
||||||
|
conditional_flush(port->r->pipe, dst, 3);
|
||||||
|
|
||||||
|
sampler.wrap_s = PIPE_TEX_WRAP_CLAMP;
|
||||||
|
sampler.wrap_t = PIPE_TEX_WRAP_CLAMP;
|
||||||
|
sampler.min_img_filter = PIPE_TEX_FILTER_LINEAR;
|
||||||
|
sampler.mag_img_filter = PIPE_TEX_FILTER_LINEAR;
|
||||||
|
sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST;
|
||||||
|
sampler.normalized_coords = 1;
|
||||||
|
|
||||||
|
samplers[0] = &sampler;
|
||||||
|
samplers[1] = &sampler;
|
||||||
|
samplers[2] = &sampler;
|
||||||
|
|
||||||
|
|
||||||
|
cso_set_samplers(port->r->cso, 3,
|
||||||
|
(const struct pipe_sampler_state **)samplers);
|
||||||
|
cso_set_sampler_textures(port->r->cso, 3,
|
||||||
|
dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
display_video(ScrnInfoPtr pScrn, struct xorg_xv_port_priv *pPriv, int id,
|
display_video(ScrnInfoPtr pScrn, struct xorg_xv_port_priv *pPriv, int id,
|
||||||
RegionPtr dstRegion,
|
RegionPtr dstRegion,
|
||||||
|
int src_x, int src_y, int src_w, int src_h,
|
||||||
|
int dstX, int dstY,
|
||||||
short width, short height,
|
short width, short height,
|
||||||
int x1, int y1, int x2, int y2,
|
|
||||||
short src_w, short src_h, short drw_w, short drw_h,
|
|
||||||
PixmapPtr pPixmap)
|
PixmapPtr pPixmap)
|
||||||
{
|
{
|
||||||
|
modesettingPtr ms = modesettingPTR(pScrn);
|
||||||
BoxPtr pbox;
|
BoxPtr pbox;
|
||||||
int nbox;
|
int nbox;
|
||||||
int dxo, dyo;
|
int dxo, dyo;
|
||||||
Bool hdtv;
|
Bool hdtv;
|
||||||
float tc0[2], tc1[2], tc2[2];
|
int x, y, w, h;
|
||||||
|
struct exa_pixmap_priv *dst = exaGetPixmapDriverPrivate(pPixmap);
|
||||||
|
|
||||||
|
if (!dst || !dst->tex)
|
||||||
|
XORG_FALLBACK("Xv destination %s", !dst ? "!dst" : "!dst->tex");
|
||||||
|
|
||||||
hdtv = ((src_w >= RES_720P_X) && (src_h >= RES_720P_Y));
|
hdtv = ((src_w >= RES_720P_X) && (src_h >= RES_720P_Y));
|
||||||
setup_video_constants(pPriv->r, hdtv);
|
|
||||||
|
|
||||||
REGION_TRANSLATE(pScrn->pScreen, dstRegion, -pPixmap->screen_x,
|
REGION_TRANSLATE(pScrn->pScreen, dstRegion, -pPixmap->screen_x,
|
||||||
-pPixmap->screen_y);
|
-pPixmap->screen_y);
|
||||||
|
|
@ -327,32 +431,32 @@ display_video(ScrnInfoPtr pScrn, struct xorg_xv_port_priv *pPriv, int id,
|
||||||
pbox = REGION_RECTS(dstRegion);
|
pbox = REGION_RECTS(dstRegion);
|
||||||
nbox = REGION_NUM_RECTS(dstRegion);
|
nbox = REGION_NUM_RECTS(dstRegion);
|
||||||
|
|
||||||
|
renderer_bind_framebuffer(pPriv->r, dst);
|
||||||
|
renderer_bind_viewport(pPriv->r, dst);
|
||||||
|
bind_blend_state(pPriv);
|
||||||
|
renderer_bind_rasterizer(pPriv->r);
|
||||||
|
bind_shaders(pPriv);
|
||||||
|
bind_samplers(pPriv);
|
||||||
|
setup_vs_video_constants(pPriv->r, dst);
|
||||||
|
setup_fs_video_constants(pPriv->r, hdtv);
|
||||||
|
|
||||||
while (nbox--) {
|
while (nbox--) {
|
||||||
int box_x1 = pbox->x1;
|
int box_x1 = pbox->x1;
|
||||||
int box_y1 = pbox->y1;
|
int box_y1 = pbox->y1;
|
||||||
int box_x2 = pbox->x2;
|
int box_x2 = pbox->x2;
|
||||||
int box_y2 = pbox->y2;
|
int box_y2 = pbox->y2;
|
||||||
|
|
||||||
tc0[0] = (double) (box_x1 - dxo) / (double) drw_w; /* u0 */
|
|
||||||
tc0[1] = (double) (box_y1 - dyo) / (double) drw_h; /* v0 */
|
|
||||||
tc1[0] = (double) (box_x2 - dxo) / (double) drw_w; /* u1 */
|
|
||||||
tc1[1] = tc0[1];
|
|
||||||
tc2[0] = tc0[0];
|
|
||||||
tc2[1] = (double) (box_y2 - dyo) / (double) drw_h; /* v1 */
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
x = box_x1;
|
x = box_x1;
|
||||||
y = box_y1;
|
y = box_y1;
|
||||||
w = box_x2 - box_x1;
|
w = box_x2 - box_x1;
|
||||||
h = box_y2 - box_y1;
|
h = box_y2 - box_y1;
|
||||||
|
|
||||||
|
draw_yuv(pPriv, x, y, x, y, w, h);
|
||||||
|
|
||||||
pbox++;
|
pbox++;
|
||||||
draw_yuv(pScrn, x, y, w, h, &src, 1, FALSE,
|
|
||||||
0, tc0, tc1, tc2, 1,
|
|
||||||
pPriv->conversionData);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
DamageDamageRegion(&pPixmap->drawable, dstRegion);
|
DamageDamageRegion(&pPixmap->drawable, dstRegion);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -412,9 +516,10 @@ put_image(ScrnInfoPtr pScrn,
|
||||||
pPixmap = (PixmapPtr)pDraw;
|
pPixmap = (PixmapPtr)pDraw;
|
||||||
}
|
}
|
||||||
|
|
||||||
display_video(pScrn, pPriv, id, clipBoxes, width, height,
|
display_video(pScrn, pPriv, id, clipBoxes,
|
||||||
x1, y1, x2, y2,
|
src_x, src_y, src_w, src_h,
|
||||||
src_w, src_h, drw_w, drw_h, pPixmap);
|
drw_x, drw_y,
|
||||||
|
drw_w, drw_h, pPixmap);
|
||||||
|
|
||||||
pPriv->current_set = (pPriv->current_set + 1) & 1;
|
pPriv->current_set = (pPriv->current_set + 1) & 1;
|
||||||
return Success;
|
return Success;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue