mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-19 04:58:08 +02:00
Viewports must be initialized with the appropriate swizzles (for
hardware that supports this feature).
Fixes: 90fcb3fef2 (st/mesa: add NV_viewport_swizzle support)
Signed-off-by: Ilia Mirkin <imirkin@alum.mit.edu>
Reviewed-By: Mike Blumenkrantz <michael.blumenkrantz@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/9732>
331 lines
9.9 KiB
C
331 lines
9.9 KiB
C
|
|
#include "frontend/graw.h"
|
|
|
|
#include "pipe/p_context.h"
|
|
#include "pipe/p_defines.h"
|
|
#include "pipe/p_screen.h"
|
|
#include "pipe/p_shader_tokens.h"
|
|
#include "pipe/p_state.h"
|
|
|
|
#include "util/u_box.h"
|
|
#include "util/u_debug.h"
|
|
#include "util/u_debug_image.h"
|
|
#include "util/u_draw_quad.h"
|
|
#include "util/format/u_format.h"
|
|
#include "util/u_inlines.h"
|
|
#include "util/u_memory.h"
|
|
|
|
|
|
struct graw_info
|
|
{
|
|
struct pipe_screen *screen;
|
|
struct pipe_context *ctx;
|
|
struct pipe_resource *color_buf[PIPE_MAX_COLOR_BUFS], *zs_buf;
|
|
struct pipe_surface *color_surf[PIPE_MAX_COLOR_BUFS], *zs_surf;
|
|
void *window;
|
|
};
|
|
|
|
|
|
|
|
static inline boolean
|
|
graw_util_create_window(struct graw_info *info,
|
|
int width, int height,
|
|
int num_cbufs, bool zstencil_buf)
|
|
{
|
|
static const enum pipe_format formats[] = {
|
|
PIPE_FORMAT_RGBA8888_UNORM,
|
|
PIPE_FORMAT_BGRA8888_UNORM,
|
|
PIPE_FORMAT_NONE
|
|
};
|
|
enum pipe_format format;
|
|
struct pipe_resource resource_temp;
|
|
struct pipe_surface surface_temp;
|
|
int i;
|
|
|
|
memset(info, 0, sizeof(*info));
|
|
memset(&resource_temp, 0, sizeof(resource_temp));
|
|
|
|
/* It's hard to say whether window or screen should be created
|
|
* first. Different environments would prefer one or the other.
|
|
*
|
|
* Also, no easy way of querying supported formats if the screen
|
|
* cannot be created first.
|
|
*/
|
|
for (i = 0; info->window == NULL && formats[i] != PIPE_FORMAT_NONE; i++) {
|
|
info->screen = graw_create_window_and_screen(0, 0, width, height,
|
|
formats[i],
|
|
&info->window);
|
|
format = formats[i];
|
|
}
|
|
if (!info->screen || !info->window) {
|
|
debug_printf("graw: Failed to create screen/window\n");
|
|
return FALSE;
|
|
}
|
|
|
|
info->ctx = info->screen->context_create(info->screen, NULL, 0);
|
|
if (info->ctx == NULL) {
|
|
debug_printf("graw: Failed to create context\n");
|
|
return FALSE;
|
|
}
|
|
|
|
for (i = 0; i < num_cbufs; i++) {
|
|
/* create color texture */
|
|
resource_temp.target = PIPE_TEXTURE_2D;
|
|
resource_temp.format = format;
|
|
resource_temp.width0 = width;
|
|
resource_temp.height0 = height;
|
|
resource_temp.depth0 = 1;
|
|
resource_temp.array_size = 1;
|
|
resource_temp.last_level = 0;
|
|
resource_temp.bind = (PIPE_BIND_RENDER_TARGET |
|
|
PIPE_BIND_DISPLAY_TARGET);
|
|
info->color_buf[i] = info->screen->resource_create(info->screen,
|
|
&resource_temp);
|
|
if (info->color_buf[i] == NULL) {
|
|
debug_printf("graw: Failed to create color texture\n");
|
|
return FALSE;
|
|
}
|
|
|
|
/* create color surface */
|
|
surface_temp.format = resource_temp.format;
|
|
surface_temp.u.tex.level = 0;
|
|
surface_temp.u.tex.first_layer = 0;
|
|
surface_temp.u.tex.last_layer = 0;
|
|
info->color_surf[i] = info->ctx->create_surface(info->ctx,
|
|
info->color_buf[i],
|
|
&surface_temp);
|
|
if (info->color_surf[i] == NULL) {
|
|
debug_printf("graw: Failed to get color surface\n");
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
/* create Z texture (XXX try other Z/S formats if needed) */
|
|
resource_temp.target = PIPE_TEXTURE_2D;
|
|
resource_temp.format = PIPE_FORMAT_S8_UINT_Z24_UNORM;
|
|
resource_temp.width0 = width;
|
|
resource_temp.height0 = height;
|
|
resource_temp.depth0 = 1;
|
|
resource_temp.array_size = 1;
|
|
resource_temp.last_level = 0;
|
|
resource_temp.bind = PIPE_BIND_DEPTH_STENCIL;
|
|
info->zs_buf = info->screen->resource_create(info->screen, &resource_temp);
|
|
if (!info->zs_buf) {
|
|
debug_printf("graw: Failed to create Z texture\n");
|
|
return FALSE;
|
|
}
|
|
|
|
/* create z surface */
|
|
surface_temp.format = resource_temp.format;
|
|
surface_temp.u.tex.level = 0;
|
|
surface_temp.u.tex.first_layer = 0;
|
|
surface_temp.u.tex.last_layer = 0;
|
|
info->zs_surf = info->ctx->create_surface(info->ctx,
|
|
info->zs_buf,
|
|
&surface_temp);
|
|
if (info->zs_surf == NULL) {
|
|
debug_printf("graw: Failed to get Z surface\n");
|
|
return FALSE;
|
|
}
|
|
|
|
{
|
|
struct pipe_framebuffer_state fb;
|
|
memset(&fb, 0, sizeof fb);
|
|
fb.nr_cbufs = num_cbufs;
|
|
fb.width = width;
|
|
fb.height = height;
|
|
for (i = 0; i < num_cbufs; i++)
|
|
fb.cbufs[i] = info->color_surf[i];
|
|
fb.zsbuf = info->zs_surf;
|
|
info->ctx->set_framebuffer_state(info->ctx, &fb);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
static inline void
|
|
graw_util_default_state(struct graw_info *info, boolean depth_test)
|
|
{
|
|
{
|
|
struct pipe_blend_state blend;
|
|
void *handle;
|
|
memset(&blend, 0, sizeof blend);
|
|
blend.rt[0].colormask = PIPE_MASK_RGBA;
|
|
handle = info->ctx->create_blend_state(info->ctx, &blend);
|
|
info->ctx->bind_blend_state(info->ctx, handle);
|
|
}
|
|
|
|
{
|
|
struct pipe_depth_stencil_alpha_state depthStencilAlpha;
|
|
void *handle;
|
|
memset(&depthStencilAlpha, 0, sizeof depthStencilAlpha);
|
|
depthStencilAlpha.depth_enabled = depth_test;
|
|
depthStencilAlpha.depth_writemask = 1;
|
|
depthStencilAlpha.depth_func = PIPE_FUNC_LESS;
|
|
handle = info->ctx->create_depth_stencil_alpha_state(info->ctx,
|
|
&depthStencilAlpha);
|
|
info->ctx->bind_depth_stencil_alpha_state(info->ctx, handle);
|
|
}
|
|
|
|
{
|
|
struct pipe_rasterizer_state rasterizer;
|
|
void *handle;
|
|
memset(&rasterizer, 0, sizeof rasterizer);
|
|
rasterizer.cull_face = PIPE_FACE_NONE;
|
|
rasterizer.half_pixel_center = 1;
|
|
rasterizer.bottom_edge_rule = 1;
|
|
handle = info->ctx->create_rasterizer_state(info->ctx, &rasterizer);
|
|
info->ctx->bind_rasterizer_state(info->ctx, handle);
|
|
}
|
|
}
|
|
|
|
|
|
static inline void
|
|
graw_util_viewport(struct graw_info *info,
|
|
float x, float y,
|
|
float width, float height,
|
|
float zNear, float zFar)
|
|
{
|
|
float z = zNear;
|
|
float half_width = width / 2.0f;
|
|
float half_height = height / 2.0f;
|
|
float half_depth = (zFar - zNear) / 2.0f;
|
|
struct pipe_viewport_state vp;
|
|
|
|
vp.scale[0] = half_width;
|
|
vp.scale[1] = half_height;
|
|
vp.scale[2] = half_depth;
|
|
|
|
vp.translate[0] = half_width + x;
|
|
vp.translate[1] = half_height + y;
|
|
vp.translate[2] = half_depth + z;
|
|
|
|
vp.swizzle_x = PIPE_VIEWPORT_SWIZZLE_POSITIVE_X;
|
|
vp.swizzle_y = PIPE_VIEWPORT_SWIZZLE_POSITIVE_Y;
|
|
vp.swizzle_z = PIPE_VIEWPORT_SWIZZLE_POSITIVE_Z;
|
|
vp.swizzle_w = PIPE_VIEWPORT_SWIZZLE_POSITIVE_W;
|
|
|
|
info->ctx->set_viewport_states(info->ctx, 0, 1, &vp);
|
|
}
|
|
|
|
|
|
static inline void
|
|
graw_util_flush_front(const struct graw_info *info)
|
|
{
|
|
info->screen->flush_frontbuffer(info->screen, info->ctx, info->color_buf[0],
|
|
0, 0, info->window, NULL);
|
|
}
|
|
|
|
|
|
static inline struct pipe_resource *
|
|
graw_util_create_tex2d(const struct graw_info *info,
|
|
int width, int height, enum pipe_format format,
|
|
const void *data)
|
|
{
|
|
const int row_stride = width * util_format_get_blocksize(format);
|
|
const int image_bytes = row_stride * height;
|
|
struct pipe_resource temp, *tex;
|
|
struct pipe_box box;
|
|
|
|
memset(&temp, 0, sizeof(temp));
|
|
temp.target = PIPE_TEXTURE_2D;
|
|
temp.format = format;
|
|
temp.width0 = width;
|
|
temp.height0 = height;
|
|
temp.depth0 = 1;
|
|
temp.last_level = 0;
|
|
temp.array_size = 1;
|
|
temp.bind = PIPE_BIND_SAMPLER_VIEW;
|
|
|
|
tex = info->screen->resource_create(info->screen, &temp);
|
|
if (!tex) {
|
|
debug_printf("graw: failed to create texture\n");
|
|
return NULL;
|
|
}
|
|
|
|
u_box_2d(0, 0, width, height, &box);
|
|
|
|
info->ctx->texture_subdata(info->ctx,
|
|
tex,
|
|
0,
|
|
PIPE_MAP_WRITE,
|
|
&box,
|
|
data,
|
|
row_stride,
|
|
image_bytes);
|
|
|
|
/* Possibly read back & compare against original data:
|
|
*/
|
|
#if 0
|
|
{
|
|
struct pipe_transfer *t;
|
|
uint32_t *ptr;
|
|
t = pipe_transfer_map(info->ctx, samptex,
|
|
0, 0, /* level, layer */
|
|
PIPE_MAP_READ,
|
|
0, 0, SIZE, SIZE); /* x, y, width, height */
|
|
|
|
ptr = info->ctx->transfer_map(info->ctx, t);
|
|
|
|
if (memcmp(ptr, tex2d, sizeof tex2d) != 0) {
|
|
assert(0);
|
|
exit(9);
|
|
}
|
|
|
|
info->ctx->transfer_unmap(info->ctx, t);
|
|
|
|
info->ctx->transfer_destroy(info->ctx, t);
|
|
}
|
|
#endif
|
|
|
|
return tex;
|
|
}
|
|
|
|
|
|
static inline void *
|
|
graw_util_create_simple_sampler(const struct graw_info *info,
|
|
unsigned wrap_mode,
|
|
unsigned img_filter)
|
|
{
|
|
struct pipe_sampler_state sampler_desc;
|
|
void *sampler;
|
|
|
|
memset(&sampler_desc, 0, sizeof sampler_desc);
|
|
sampler_desc.wrap_s =
|
|
sampler_desc.wrap_t =
|
|
sampler_desc.wrap_r = wrap_mode;
|
|
sampler_desc.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
|
|
sampler_desc.min_img_filter =
|
|
sampler_desc.mag_img_filter = img_filter;
|
|
sampler_desc.compare_mode = PIPE_TEX_COMPARE_NONE;
|
|
sampler_desc.compare_func = 0;
|
|
sampler_desc.normalized_coords = 1;
|
|
sampler_desc.max_anisotropy = 0;
|
|
|
|
sampler = info->ctx->create_sampler_state(info->ctx, &sampler_desc);
|
|
|
|
return sampler;
|
|
}
|
|
|
|
|
|
static inline struct pipe_sampler_view *
|
|
graw_util_create_simple_sampler_view(const struct graw_info *info,
|
|
struct pipe_resource *texture)
|
|
{
|
|
struct pipe_sampler_view sv_temp;
|
|
struct pipe_sampler_view *sv;
|
|
|
|
memset(&sv_temp, 0, sizeof(sv_temp));
|
|
sv_temp.format = texture->format;
|
|
sv_temp.texture = texture;
|
|
sv_temp.swizzle_r = PIPE_SWIZZLE_X;
|
|
sv_temp.swizzle_g = PIPE_SWIZZLE_Y;
|
|
sv_temp.swizzle_b = PIPE_SWIZZLE_Z;
|
|
sv_temp.swizzle_a = PIPE_SWIZZLE_W;
|
|
|
|
sv = info->ctx->create_sampler_view(info->ctx, texture, &sv_temp);
|
|
|
|
return sv;
|
|
}
|
|
|