Browse Source

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.
tags/mesa-7.9-rc1
Chia-I Wu 15 years ago
parent
commit
76708c665c
1 changed files with 239 additions and 24 deletions
  1. 239
    24
      src/gallium/state_trackers/vega/vg_manager.c

+ 239
- 24
src/gallium/state_trackers/vega/vg_manager.c View File

@@ -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…
Cancel
Save