mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-06 05:08:08 +02:00
st/vega: Do not rely on st_resize_framebuffer.
Add vg_context_update_draw_buffer (and helpers) that duplicates the logic of st_resize_framebuffer. Use the new function instead of st_resize_framebuffer in vg_manager.c.
This commit is contained in:
parent
50409dd71b
commit
76708c665c
1 changed files with 239 additions and 24 deletions
|
|
@ -2,6 +2,7 @@
|
|||
* Mesa 3-D graphics library
|
||||
* Version: 7.9
|
||||
*
|
||||
* Copyright 2009 VMware, Inc. All Rights Reserved.
|
||||
* Copyright (C) 2010 LunarG Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
|
|
@ -33,11 +34,242 @@
|
|||
#include "util/u_memory.h"
|
||||
#include "util/u_inlines.h"
|
||||
#include "util/u_format.h"
|
||||
#include "util/u_sampler.h"
|
||||
|
||||
#include "vg_manager.h"
|
||||
#include "vg_context.h"
|
||||
#include "vg_tracker.h" /* for st_resize_framebuffer */
|
||||
#include "image.h"
|
||||
#include "mask.h"
|
||||
|
||||
static struct pipe_resource *
|
||||
create_texture(struct pipe_context *pipe, enum pipe_format format,
|
||||
VGint width, VGint height)
|
||||
{
|
||||
struct pipe_resource templ;
|
||||
|
||||
memset(&templ, 0, sizeof(templ));
|
||||
|
||||
if (format != PIPE_FORMAT_NONE) {
|
||||
templ.format = format;
|
||||
}
|
||||
else {
|
||||
templ.format = PIPE_FORMAT_B8G8R8A8_UNORM;
|
||||
}
|
||||
|
||||
templ.target = PIPE_TEXTURE_2D;
|
||||
templ.width0 = width;
|
||||
templ.height0 = height;
|
||||
templ.depth0 = 1;
|
||||
templ.last_level = 0;
|
||||
|
||||
if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_ZS, 1)) {
|
||||
templ.bind = PIPE_BIND_DEPTH_STENCIL;
|
||||
} else {
|
||||
templ.bind = (PIPE_BIND_DISPLAY_TARGET |
|
||||
PIPE_BIND_RENDER_TARGET |
|
||||
PIPE_BIND_SAMPLER_VIEW);
|
||||
}
|
||||
|
||||
return pipe->screen->resource_create(pipe->screen, &templ);
|
||||
}
|
||||
|
||||
static struct pipe_sampler_view *
|
||||
create_tex_and_view(struct pipe_context *pipe, enum pipe_format format,
|
||||
VGint width, VGint height)
|
||||
{
|
||||
struct pipe_resource *texture;
|
||||
struct pipe_sampler_view view_templ;
|
||||
struct pipe_sampler_view *view;
|
||||
|
||||
texture = create_texture(pipe, format, width, height);
|
||||
|
||||
if (!texture)
|
||||
return NULL;
|
||||
|
||||
u_sampler_view_default_template(&view_templ, texture, texture->format);
|
||||
view = pipe->create_sampler_view(pipe, texture, &view_templ);
|
||||
/* want the texture to go away if the view is freed */
|
||||
pipe_resource_reference(&texture, NULL);
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
static void
|
||||
setup_new_alpha_mask(struct vg_context *ctx, struct st_framebuffer *stfb)
|
||||
{
|
||||
struct pipe_context *pipe = ctx->pipe;
|
||||
struct pipe_sampler_view *old_sampler_view = stfb->alpha_mask_view;
|
||||
|
||||
/*
|
||||
we use PIPE_FORMAT_B8G8R8A8_UNORM because we want to render to
|
||||
this texture and use it as a sampler, so while this wastes some
|
||||
space it makes both of those a lot simpler
|
||||
*/
|
||||
stfb->alpha_mask_view = create_tex_and_view(pipe,
|
||||
PIPE_FORMAT_B8G8R8A8_UNORM, stfb->width, stfb->height);
|
||||
|
||||
if (!stfb->alpha_mask_view) {
|
||||
if (old_sampler_view)
|
||||
pipe_sampler_view_reference(&old_sampler_view, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
/* XXX could this call be avoided? */
|
||||
vg_validate_state(ctx);
|
||||
|
||||
/* alpha mask starts with 1.f alpha */
|
||||
mask_fill(0, 0, stfb->width, stfb->height, 1.f);
|
||||
|
||||
/* if we had an old surface copy it over */
|
||||
if (old_sampler_view) {
|
||||
struct pipe_surface *surface = pipe->screen->get_tex_surface(
|
||||
pipe->screen,
|
||||
stfb->alpha_mask_view->texture,
|
||||
0, 0, 0,
|
||||
PIPE_BIND_RENDER_TARGET |
|
||||
PIPE_BIND_BLIT_DESTINATION);
|
||||
struct pipe_surface *old_surface = pipe->screen->get_tex_surface(
|
||||
pipe->screen,
|
||||
old_sampler_view->texture,
|
||||
0, 0, 0,
|
||||
PIPE_BIND_BLIT_SOURCE);
|
||||
pipe->surface_copy(pipe,
|
||||
surface,
|
||||
0, 0,
|
||||
old_surface,
|
||||
0, 0,
|
||||
MIN2(old_surface->width, surface->width),
|
||||
MIN2(old_surface->height, surface->height));
|
||||
if (surface)
|
||||
pipe_surface_reference(&surface, NULL);
|
||||
if (old_surface)
|
||||
pipe_surface_reference(&old_surface, NULL);
|
||||
}
|
||||
|
||||
/* Free the old texture
|
||||
*/
|
||||
if (old_sampler_view)
|
||||
pipe_sampler_view_reference(&old_sampler_view, NULL);
|
||||
}
|
||||
|
||||
static boolean
|
||||
vg_context_update_depth_stencil_rb(struct vg_context * ctx,
|
||||
uint width, uint height)
|
||||
{
|
||||
struct st_renderbuffer *dsrb = ctx->draw_buffer->dsrb;
|
||||
struct pipe_context *pipe = ctx->pipe;
|
||||
unsigned surface_usage;
|
||||
|
||||
if ((dsrb->width == width && dsrb->height == height) && dsrb->texture)
|
||||
return FALSE;
|
||||
|
||||
/* unreference existing ones */
|
||||
pipe_surface_reference(&dsrb->surface, NULL);
|
||||
pipe_resource_reference(&dsrb->texture, NULL);
|
||||
dsrb->width = dsrb->height = 0;
|
||||
|
||||
/* Probably need dedicated flags for surface usage too:
|
||||
*/
|
||||
surface_usage = (PIPE_BIND_RENDER_TARGET |
|
||||
PIPE_BIND_BLIT_SOURCE |
|
||||
PIPE_BIND_BLIT_DESTINATION);
|
||||
|
||||
dsrb->texture = create_texture(pipe, dsrb->format, width, height);
|
||||
if (!dsrb->texture)
|
||||
return TRUE;
|
||||
|
||||
dsrb->surface = pipe->screen->get_tex_surface(pipe->screen,
|
||||
dsrb->texture,
|
||||
0, 0, 0,
|
||||
surface_usage);
|
||||
if (!dsrb->surface) {
|
||||
pipe_resource_reference(&dsrb->texture, NULL);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
dsrb->width = width;
|
||||
dsrb->height = height;
|
||||
|
||||
assert(dsrb->surface->width == width);
|
||||
assert(dsrb->surface->height == height);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static boolean
|
||||
vg_context_update_color_rb(struct vg_context *ctx, struct pipe_resource *pt)
|
||||
{
|
||||
struct st_renderbuffer *strb = ctx->draw_buffer->strb;
|
||||
struct pipe_screen *screen = ctx->pipe->screen;
|
||||
|
||||
if (strb->texture == pt) {
|
||||
pipe_resource_reference(&pt, NULL);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* unreference existing ones */
|
||||
pipe_surface_reference(&strb->surface, NULL);
|
||||
pipe_resource_reference(&strb->texture, NULL);
|
||||
strb->width = strb->height = 0;
|
||||
|
||||
strb->texture = pt;
|
||||
strb->surface = screen->get_tex_surface(screen, strb->texture, 0, 0, 0,
|
||||
PIPE_BIND_RENDER_TARGET |
|
||||
PIPE_BIND_BLIT_SOURCE |
|
||||
PIPE_BIND_BLIT_DESTINATION);
|
||||
if (!strb->surface) {
|
||||
pipe_resource_reference(&strb->texture, NULL);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
strb->width = pt->width0;
|
||||
strb->height = pt->height0;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
vg_context_update_draw_buffer(struct vg_context *ctx, struct pipe_resource *pt)
|
||||
{
|
||||
struct st_framebuffer *stfb = ctx->draw_buffer;
|
||||
boolean new_cbuf, new_zsbuf, new_size;
|
||||
|
||||
new_cbuf = vg_context_update_color_rb(ctx, pt);
|
||||
new_zsbuf =
|
||||
vg_context_update_depth_stencil_rb(ctx, pt->width0, pt->height0);
|
||||
|
||||
new_size = (stfb->width != pt->width0 || stfb->height != pt->height0);
|
||||
stfb->width = pt->width0;
|
||||
stfb->height = pt->height0;
|
||||
|
||||
if (new_cbuf || new_zsbuf || new_size) {
|
||||
struct pipe_framebuffer_state *state = &ctx->state.g3d.fb;
|
||||
|
||||
memset(state, 0, sizeof(struct pipe_framebuffer_state));
|
||||
state->width = stfb->width;
|
||||
state->height = stfb->height;
|
||||
state->nr_cbufs = 1;
|
||||
state->cbufs[0] = stfb->strb->surface;
|
||||
state->zsbuf = stfb->dsrb->surface;
|
||||
|
||||
cso_set_framebuffer(ctx->cso_context, state);
|
||||
}
|
||||
|
||||
if (new_zsbuf || new_size) {
|
||||
ctx->state.dirty |= VIEWPORT_DIRTY;
|
||||
ctx->state.dirty |= DEPTH_STENCIL_DIRTY;/*to reset the scissors*/
|
||||
|
||||
ctx->pipe->clear(ctx->pipe, PIPE_CLEAR_DEPTHSTENCIL, NULL, 0.0, 0);
|
||||
|
||||
/* we need all the other state already set */
|
||||
|
||||
setup_new_alpha_mask(ctx, stfb);
|
||||
|
||||
pipe_sampler_view_reference( &stfb->blend_texture_view, NULL);
|
||||
stfb->blend_texture_view = create_tex_and_view(ctx->pipe,
|
||||
PIPE_FORMAT_B8G8R8A8_UNORM, stfb->width, stfb->height);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush the front buffer if the current context renders to the front buffer.
|
||||
|
|
@ -76,9 +308,7 @@ vg_manager_flush_frontbuffer(struct vg_context *ctx)
|
|||
void
|
||||
vg_manager_validate_framebuffer(struct vg_context *ctx)
|
||||
{
|
||||
struct pipe_screen *screen = ctx->pipe->screen;
|
||||
struct st_framebuffer *stfb = ctx->draw_buffer;
|
||||
struct st_renderbuffer *rb;
|
||||
struct pipe_resource *pt;
|
||||
|
||||
/* no binding surface */
|
||||
|
|
@ -100,28 +330,13 @@ vg_manager_validate_framebuffer(struct vg_context *ctx)
|
|||
if (!stfb->iface->validate(stfb->iface, &stfb->strb_att, 1, &pt) || !pt)
|
||||
return;
|
||||
|
||||
rb = stfb->strb;
|
||||
if (rb->texture == pt) {
|
||||
pipe_resource_reference(&pt, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
/* unreference existing ones */
|
||||
pipe_surface_reference(&rb->surface, NULL);
|
||||
pipe_resource_reference(&rb->texture, NULL);
|
||||
|
||||
rb->texture = pt;
|
||||
rb->surface = screen->get_tex_surface(screen, rb->texture, 0, 0, 0,
|
||||
PIPE_BIND_RENDER_TARGET |
|
||||
PIPE_BIND_BLIT_SOURCE |
|
||||
PIPE_BIND_BLIT_DESTINATION);
|
||||
|
||||
rb->width = rb->surface->width;
|
||||
rb->height = rb->surface->height;
|
||||
|
||||
st_resize_framebuffer(stfb, rb->width, rb->height);
|
||||
|
||||
/*
|
||||
* unset draw_buffer_invalid first because vg_context_update_draw_buffer
|
||||
* will cause the framebuffer to be validated again because of a call to
|
||||
* vg_validate_state
|
||||
*/
|
||||
p_atomic_set(&ctx->draw_buffer_invalid, FALSE);
|
||||
vg_context_update_draw_buffer(ctx, pt);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue