Merge remote branch 'origin/gallium-st-api-dri'

This commit is contained in:
Chia-I Wu 2010-03-21 16:32:34 +08:00
commit 12deb9e6ca
14 changed files with 1348 additions and 907 deletions

View file

@ -15,7 +15,9 @@ C_SOURCES = \
dri_context.c \ dri_context.c \
dri_screen.c \ dri_screen.c \
dri_drawable.c \ dri_drawable.c \
dri_extensions.c dri_extensions.c \
dri_st_api.c \
dri1.c
# $(TOP)/src/mesa/drivers/dri/common/utils.c \ # $(TOP)/src/mesa/drivers/dri/common/utils.c \
$(TOP)/src/mesa/drivers/dri/common/vblank.c \ $(TOP)/src/mesa/drivers/dri/common/vblank.c \

View file

@ -18,6 +18,8 @@ if env['dri']:
'dri_drawable.c', 'dri_drawable.c',
'dri_extensions.c', 'dri_extensions.c',
'dri_screen.c', 'dri_screen.c',
'dri_st_api.c',
'dri1.c',
] ]
) )
Export('st_dri') Export('st_dri')

View file

@ -0,0 +1,583 @@
/**************************************************************************
*
* Copyright 2009, VMware, Inc.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
/*
* Author: Keith Whitwell <keithw@vmware.com>
* Author: Jakob Bornecrantz <wallbraker@gmail.com>
*/
/* XXX DRI1 is untested after the switch to st_api.h */
#include "util/u_memory.h"
#include "util/u_rect.h"
#include "util/u_inlines.h"
#include "pipe/p_context.h"
#include "state_tracker/dri1_api.h"
#include "dri_screen.h"
#include "dri_context.h"
#include "dri_drawable.h"
#include "dri_st_api.h"
#include "dri1.h"
static INLINE void
dri1_lock(struct dri_context *ctx)
{
drm_context_t hw_context = ctx->cPriv->hHWContext;
char ret = 0;
DRM_CAS(ctx->lock, hw_context, DRM_LOCK_HELD | hw_context, ret);
if (ret) {
drmGetLock(ctx->sPriv->fd, hw_context, 0);
ctx->stLostLock = TRUE;
ctx->wsLostLock = TRUE;
}
ctx->isLocked = TRUE;
}
static INLINE void
dri1_unlock(struct dri_context *ctx)
{
ctx->isLocked = FALSE;
DRM_UNLOCK(ctx->sPriv->fd, ctx->lock, ctx->cPriv->hHWContext);
}
static struct pipe_fence_handle *
dri_swap_fences_pop_front(struct dri_drawable *draw)
{
struct pipe_screen *screen = dri_screen(draw->sPriv)->pipe_screen;
struct pipe_fence_handle *fence = NULL;
if (draw->cur_fences >= draw->desired_fences) {
screen->fence_reference(screen, &fence, draw->swap_fences[draw->tail]);
screen->fence_reference(screen, &draw->swap_fences[draw->tail++], NULL);
--draw->cur_fences;
draw->tail &= DRI_SWAP_FENCES_MASK;
}
return fence;
}
static void
dri_swap_fences_push_back(struct dri_drawable *draw,
struct pipe_fence_handle *fence)
{
struct pipe_screen *screen = dri_screen(draw->sPriv)->pipe_screen;
if (!fence)
return;
if (draw->cur_fences < DRI_SWAP_FENCES_MAX) {
draw->cur_fences++;
screen->fence_reference(screen, &draw->swap_fences[draw->head++],
fence);
draw->head &= DRI_SWAP_FENCES_MASK;
}
}
void
dri1_swap_fences_clear(struct dri_drawable *drawable)
{
struct pipe_screen *screen = dri_screen(drawable->sPriv)->pipe_screen;
struct pipe_fence_handle *fence;
while (drawable->cur_fences) {
fence = dri_swap_fences_pop_front(drawable);
screen->fence_reference(screen, &fence, NULL);
}
}
static void
dri1_update_drawables_locked(struct dri_context *ctx,
__DRIdrawable * driDrawPriv,
__DRIdrawable * driReadPriv)
{
if (ctx->stLostLock) {
ctx->stLostLock = FALSE;
if (driDrawPriv == driReadPriv)
DRI_VALIDATE_DRAWABLE_INFO(ctx->sPriv, driDrawPriv);
else
DRI_VALIDATE_TWO_DRAWABLES_INFO(ctx->sPriv, driDrawPriv,
driReadPriv);
}
}
/**
* This ensures all contexts which bind to a drawable pick up the
* drawable change and signal new buffer state.
*/
static void
dri1_propagate_drawable_change(struct dri_context *ctx)
{
__DRIdrawable *dPriv = ctx->dPriv;
__DRIdrawable *rPriv = ctx->rPriv;
struct dri_drawable *draw = dri_drawable(dPriv);
struct dri_drawable *read = dri_drawable(rPriv);
boolean flushed = FALSE;
if (dPriv && draw->texture_stamp != dPriv->lastStamp) {
ctx->st->flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL);
flushed = TRUE;
ctx->st->notify_invalid_framebuffer(ctx->st, draw->stfb);
}
if (rPriv && dPriv != rPriv && read->texture_stamp != rPriv->lastStamp) {
if (!flushed)
ctx->st->flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL);
ctx->st->notify_invalid_framebuffer(ctx->st, read->stfb);
}
}
static INLINE boolean
dri1_intersect_src_bbox(struct drm_clip_rect *dst,
int dst_x,
int dst_y,
const struct drm_clip_rect *src,
const struct drm_clip_rect *bbox)
{
int xy1;
int xy2;
xy1 = ((int)src->x1 > (int)bbox->x1 + dst_x) ? src->x1 :
(int)bbox->x1 + dst_x;
xy2 = ((int)src->x2 < (int)bbox->x2 + dst_x) ? src->x2 :
(int)bbox->x2 + dst_x;
if (xy1 >= xy2 || xy1 < 0)
return FALSE;
dst->x1 = xy1;
dst->x2 = xy2;
xy1 = ((int)src->y1 > (int)bbox->y1 + dst_y) ? src->y1 :
(int)bbox->y1 + dst_y;
xy2 = ((int)src->y2 < (int)bbox->y2 + dst_y) ? src->y2 :
(int)bbox->y2 + dst_y;
if (xy1 >= xy2 || xy1 < 0)
return FALSE;
dst->y1 = xy1;
dst->y2 = xy2;
return TRUE;
}
static void
dri1_swap_copy(struct pipe_context *pipe,
struct pipe_surface *dst,
struct pipe_surface *src,
__DRIdrawable * dPriv, const struct drm_clip_rect *bbox)
{
struct drm_clip_rect clip;
struct drm_clip_rect *cur;
int i;
cur = dPriv->pClipRects;
for (i = 0; i < dPriv->numClipRects; ++i) {
if (dri1_intersect_src_bbox(&clip, dPriv->x, dPriv->y, cur++, bbox)) {
if (pipe->surface_copy) {
pipe->surface_copy(pipe, dst, clip.x1, clip.y1,
src,
(int)clip.x1 - dPriv->x,
(int)clip.y1 - dPriv->y,
clip.x2 - clip.x1, clip.y2 - clip.y1);
} else {
util_surface_copy(pipe, FALSE, dst, clip.x1, clip.y1,
src,
(int)clip.x1 - dPriv->x,
(int)clip.y1 - dPriv->y,
clip.x2 - clip.x1, clip.y2 - clip.y1);
}
}
}
}
static struct pipe_surface *
dri1_get_pipe_surface(struct dri_drawable *drawable, struct pipe_texture *ptex)
{
struct pipe_screen *pipe_screen = dri_screen(drawable->sPriv)->pipe_screen;
struct pipe_surface *psurf = drawable->dri1_surface;
if (!psurf || psurf->texture != ptex) {
pipe_surface_reference(&drawable->dri1_surface, NULL);
drawable->dri1_surface = pipe_screen->get_tex_surface(pipe_screen,
ptex, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_READ);
psurf = drawable->dri1_surface;
}
return psurf;
}
static struct pipe_context *
dri1_get_pipe_context(struct dri_drawable *drawable)
{
struct dri_screen *screen = dri_screen(drawable->sPriv);
struct pipe_context *pipe = screen->dri1_pipe;
if (!pipe) {
screen->dri1_pipe =
screen->pipe_screen->context_create(screen->pipe_screen, NULL);
pipe = screen->dri1_pipe;
}
return pipe;
}
static void
dri1_present_texture_locked(__DRIdrawable * dPriv,
struct pipe_texture *ptex,
const struct drm_clip_rect *sub_box,
struct pipe_fence_handle **fence)
{
struct dri_drawable *drawable = dri_drawable(dPriv);
struct pipe_context *pipe;
struct pipe_surface *psurf;
struct drm_clip_rect bbox;
boolean visible = TRUE;
*fence = NULL;
bbox.x1 = 0;
bbox.x2 = ptex->width0;
bbox.y1 = 0;
bbox.y2 = ptex->height0;
if (sub_box)
visible = dri1_intersect_src_bbox(&bbox, 0, 0, &bbox, sub_box);
if (!visible)
return;
pipe = dri1_get_pipe_context(drawable);
psurf = dri1_get_pipe_surface(drawable, ptex);
if (!pipe || !psurf)
return;
if (__dri1_api_hooks->present_locked) {
__dri1_api_hooks->present_locked(pipe, psurf,
dPriv->pClipRects, dPriv->numClipRects,
dPriv->x, dPriv->y, &bbox, fence);
} else if (__dri1_api_hooks->front_srf_locked) {
struct pipe_surface *front = __dri1_api_hooks->front_srf_locked(pipe);
if (front)
dri1_swap_copy(pipe, front, psurf, dPriv, &bbox);
pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, fence);
}
}
static void
dri1_copy_to_front(struct dri_context *ctx,
struct pipe_texture *ptex,
__DRIdrawable * dPriv,
const struct drm_clip_rect *sub_box,
struct pipe_fence_handle **fence)
{
boolean save_lost_lock;
dri1_lock(ctx);
save_lost_lock = ctx->stLostLock;
dri1_update_drawables_locked(ctx, dPriv, dPriv);
dri1_present_texture_locked(dPriv, ptex, sub_box, fence);
ctx->stLostLock = save_lost_lock;
/**
* FIXME: Revisit this: Update drawables on copy_sub_buffer ?
*/
if (!sub_box)
dri1_update_drawables_locked(ctx, ctx->dPriv, ctx->rPriv);
dri1_unlock(ctx);
dri1_propagate_drawable_change(ctx);
}
void
dri1_flush_frontbuffer(struct dri_drawable *drawable,
struct pipe_texture *ptex)
{
struct st_api *stapi = dri_get_st_api();
struct dri_screen *screen = dri_screen(drawable->sPriv);
struct pipe_screen *pipe_screen = screen->pipe_screen;
struct dri_context *ctx;
struct pipe_fence_handle *dummy_fence;
struct st_context_iface *st = stapi->get_current(stapi);
if (!st)
return;
ctx = (struct dri_context *) st->st_manager_private;
dri1_copy_to_front(ctx, ptex, ctx->dPriv, NULL, &dummy_fence);
pipe_screen->fence_reference(pipe_screen, &dummy_fence, NULL);
/**
* FIXME: Do we need swap throttling here?
*/
}
void
dri1_swap_buffers(__DRIdrawable * dPriv)
{
struct dri_context *ctx = dri_get_current();
struct dri_drawable *draw = dri_drawable(dPriv);
struct dri_screen *screen = dri_screen(draw->sPriv);
struct pipe_screen *pipe_screen = screen->pipe_screen;
struct pipe_fence_handle *fence;
struct pipe_texture *ptex;
assert(__dri1_api_hooks != NULL);
if (!ctx)
return; /* For now */
ptex = draw->textures[ST_ATTACHMENT_BACK_LEFT];
if (ptex) {
ctx->st->flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL);
fence = dri_swap_fences_pop_front(draw);
if (fence) {
(void)pipe_screen->fence_finish(pipe_screen, fence, 0);
pipe_screen->fence_reference(pipe_screen, &fence, NULL);
}
dri1_copy_to_front(ctx, ptex, dPriv, NULL, &fence);
dri_swap_fences_push_back(draw, fence);
pipe_screen->fence_reference(pipe_screen, &fence, NULL);
}
}
void
dri1_copy_sub_buffer(__DRIdrawable * dPriv, int x, int y, int w, int h)
{
struct dri_context *ctx = dri_get_current();
struct dri_screen *screen = dri_screen(dPriv->driScreenPriv);
struct pipe_screen *pipe_screen = screen->pipe_screen;
struct drm_clip_rect sub_bbox;
struct dri_drawable *draw = dri_drawable(dPriv);
struct pipe_fence_handle *dummy_fence;
struct pipe_texture *ptex;
assert(__dri1_api_hooks != NULL);
if (!ctx)
return;
sub_bbox.x1 = x;
sub_bbox.x2 = x + w;
sub_bbox.y1 = y;
sub_bbox.y2 = y + h;
ptex = draw->textures[ST_ATTACHMENT_BACK_LEFT];
if (ptex) {
ctx->st->flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL);
dri1_copy_to_front(ctx, ptex, dPriv, &sub_bbox, &dummy_fence);
pipe_screen->fence_reference(pipe_screen, &dummy_fence, NULL);
}
}
void
dri1_allocate_textures(struct dri_drawable *drawable,
unsigned width, unsigned height,
unsigned mask)
{
struct dri_screen *screen = dri_screen(drawable->sPriv);
struct pipe_texture templ;
int i;
/* remove outdated textures */
if (drawable->old_w != width || drawable->old_h != height) {
for (i = 0; i < ST_ATTACHMENT_COUNT; i++)
pipe_texture_reference(&drawable->textures[i], NULL);
}
memset(&templ, 0, sizeof(templ));
templ.target = PIPE_TEXTURE_2D;
templ.width0 = width;
templ.height0 = height;
templ.depth0 = 1;
templ.last_level = 0;
for (i = 0; i < ST_ATTACHMENT_COUNT; i++) {
enum pipe_format format;
unsigned tex_usage;
/* the texture already exists or not requested */
if (drawable->textures[i] || !(mask & (1 << i))) {
/* remember the texture */
if (drawable->textures[i])
mask |= (1 << i);
continue;
}
switch (i) {
case ST_ATTACHMENT_FRONT_LEFT:
case ST_ATTACHMENT_BACK_LEFT:
case ST_ATTACHMENT_FRONT_RIGHT:
case ST_ATTACHMENT_BACK_RIGHT:
format = drawable->stvis.color_format;
tex_usage = PIPE_TEXTURE_USAGE_DISPLAY_TARGET |
PIPE_TEXTURE_USAGE_RENDER_TARGET;
break;
case ST_ATTACHMENT_DEPTH_STENCIL:
format = drawable->stvis.depth_stencil_format;
tex_usage = PIPE_TEXTURE_USAGE_DEPTH_STENCIL;
break;
default:
format = PIPE_FORMAT_NONE;
break;
}
if (format != PIPE_FORMAT_NONE) {
templ.format = format;
templ.tex_usage = tex_usage;
drawable->textures[i] =
screen->pipe_screen->texture_create(screen->pipe_screen, &templ);
}
}
drawable->old_w = width;
drawable->old_h = height;
drawable->texture_mask = mask;
}
static void
st_dri_lock(struct pipe_context *pipe)
{
dri1_lock((struct dri_context *)pipe->priv);
}
static void
st_dri_unlock(struct pipe_context *pipe)
{
dri1_unlock((struct dri_context *)pipe->priv);
}
static boolean
st_dri_is_locked(struct pipe_context *pipe)
{
return ((struct dri_context *)pipe->priv)->isLocked;
}
static boolean
st_dri_lost_lock(struct pipe_context *pipe)
{
return ((struct dri_context *)pipe->priv)->wsLostLock;
}
static void
st_dri_clear_lost_lock(struct pipe_context *pipe)
{
((struct dri_context *)pipe->priv)->wsLostLock = FALSE;
}
static struct dri1_api_lock_funcs dri1_lf = {
.lock = st_dri_lock,
.unlock = st_dri_unlock,
.is_locked = st_dri_is_locked,
.is_lock_lost = st_dri_lost_lock,
.clear_lost_lock = st_dri_clear_lost_lock
};
static const __DRIextension *dri1_screen_extensions[] = {
&driReadDrawableExtension,
&driCopySubBufferExtension.base,
&driSwapControlExtension.base,
&driFrameTrackingExtension.base,
&driMediaStreamCounterExtension.base,
NULL
};
struct dri1_api *__dri1_api_hooks = NULL;
static INLINE void
dri1_copy_version(struct dri1_api_version *dst,
const struct __DRIversionRec *src)
{
dst->major = src->major;
dst->minor = src->minor;
dst->patch_level = src->patch;
}
const __DRIconfig **
dri1_init_screen(__DRIscreen * sPriv)
{
struct dri_screen *screen;
const __DRIconfig **configs;
struct dri1_create_screen_arg arg;
screen = CALLOC_STRUCT(dri_screen);
if (!screen)
return NULL;
screen->api = drm_api_create();
screen->sPriv = sPriv;
screen->fd = sPriv->fd;
screen->drmLock = (drmLock *) & sPriv->pSAREA->lock;
sPriv->private = (void *)screen;
sPriv->extensions = dri1_screen_extensions;
arg.base.mode = DRM_CREATE_DRI1;
arg.lf = &dri1_lf;
arg.ddx_info = sPriv->pDevPriv;
arg.ddx_info_size = sPriv->devPrivSize;
arg.sarea = sPriv->pSAREA;
dri1_copy_version(&arg.ddx_version, &sPriv->ddx_version);
dri1_copy_version(&arg.dri_version, &sPriv->dri_version);
dri1_copy_version(&arg.drm_version, &sPriv->drm_version);
arg.api = NULL;
screen->pipe_screen = screen->api->create_screen(screen->api, screen->fd, &arg.base);
if (!screen->pipe_screen || !arg.api) {
debug_printf("%s: failed to create dri1 screen\n", __FUNCTION__);
goto out_no_screen;
}
__dri1_api_hooks = arg.api;
driParseOptionInfo(&screen->optionCache,
__driConfigOptions, __driNConfigOptions);
/**
* FIXME: If the driver supports format conversion swapbuffer blits, we might
* want to support other color bit depths than the server is currently
* using.
*/
configs = dri_fill_in_modes(screen, sPriv->fbBPP);
if (!configs)
goto out_no_configs;
return configs;
out_no_configs:
screen->pipe_screen->destroy(screen->pipe_screen);
out_no_screen:
FREE(screen);
return NULL;
}

View file

@ -0,0 +1,63 @@
/**************************************************************************
*
* Copyright 2009, VMware, Inc.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
/*
* Author: Keith Whitwell <keithw@vmware.com>
* Author: Jakob Bornecrantz <wallbraker@gmail.com>
*/
#ifndef DRI1_H
#define DRI1_H
#include "dri_context.h"
#include "dri_drawable.h"
#include "state_tracker/st_api.h"
#include "dri_util.h"
extern struct dri1_api *__dri1_api_hooks;
const __DRIconfig **
dri1_init_screen(__DRIscreen * sPriv);
void
dri1_flush_frontbuffer(struct dri_drawable *drawable,
struct pipe_texture *ptex);
void
dri1_allocate_textures(struct dri_drawable *drawable,
unsigned width, unsigned height,
unsigned mask);
void dri1_swap_buffers(__DRIdrawable * dPriv);
void
dri1_copy_sub_buffer(__DRIdrawable * dPriv, int x, int y, int w, int h);
void
dri1_swap_fences_clear(struct dri_drawable *drawable);
#endif /* DRI1_H */

View file

@ -30,25 +30,24 @@
*/ */
#include "dri_screen.h" #include "dri_screen.h"
#include "dri_drawable.h" #include "dri_drawable.h"
#include "state_tracker/drm_api.h"
#include "state_tracker/dri1_api.h"
#include "state_tracker/st_public.h"
#include "pipe/p_context.h"
#include "dri_context.h" #include "dri_context.h"
#include "dri_st_api.h"
#include "dri1.h"
#include "pipe/p_context.h"
#include "util/u_memory.h" #include "util/u_memory.h"
GLboolean GLboolean
dri_create_context(const __GLcontextModes * visual, dri_create_context(const __GLcontextModes * visual,
__DRIcontext * cPriv, void *sharedContextPrivate) __DRIcontext * cPriv, void *sharedContextPrivate)
{ {
struct st_api *stapi = dri_get_st_api();
__DRIscreen *sPriv = cPriv->driScreenPriv; __DRIscreen *sPriv = cPriv->driScreenPriv;
struct dri_screen *screen = dri_screen(sPriv); struct dri_screen *screen = dri_screen(sPriv);
struct dri_context *ctx = NULL; struct dri_context *ctx = NULL;
struct st_context *st_share = NULL; struct st_context_iface *st_share = NULL;
struct st_visual stvis;
if (sharedContextPrivate) { if (sharedContextPrivate) {
st_share = ((struct dri_context *)sharedContextPrivate)->st; st_share = ((struct dri_context *)sharedContextPrivate)->st;
@ -62,21 +61,15 @@ dri_create_context(const __GLcontextModes * visual,
ctx->cPriv = cPriv; ctx->cPriv = cPriv;
ctx->sPriv = sPriv; ctx->sPriv = sPriv;
ctx->lock = screen->drmLock; ctx->lock = screen->drmLock;
ctx->d_stamp = -1;
ctx->r_stamp = -1;
driParseConfigFiles(&ctx->optionCache, driParseConfigFiles(&ctx->optionCache,
&screen->optionCache, sPriv->myNum, "dri"); &screen->optionCache, sPriv->myNum, "dri");
ctx->pipe = screen->pipe_screen->context_create( screen->pipe_screen, dri_fill_st_visual(&stvis, screen, visual);
ctx ); ctx->st = stapi->create_context(stapi, screen->smapi, &stvis, st_share);
if (ctx->pipe == NULL)
goto fail;
ctx->st = st_create_context(ctx->pipe, visual, st_share);
if (ctx->st == NULL) if (ctx->st == NULL)
goto fail; goto fail;
ctx->st->st_manager_private = (void *) ctx;
dri_init_extensions(ctx); dri_init_extensions(ctx);
@ -84,10 +77,7 @@ dri_create_context(const __GLcontextModes * visual,
fail: fail:
if (ctx && ctx->st) if (ctx && ctx->st)
st_destroy_context(ctx->st); ctx->st->destroy(ctx->st);
if (ctx && ctx->pipe)
ctx->pipe->destroy(ctx->pipe);
FREE(ctx); FREE(ctx);
return FALSE; return FALSE;
@ -109,11 +99,8 @@ dri_destroy_context(__DRIcontext * cPriv)
* to avoid having to add code elsewhere to cope with flushing a * to avoid having to add code elsewhere to cope with flushing a
* partially destroyed context. * partially destroyed context.
*/ */
st_flush(ctx->st, 0, NULL); ctx->st->flush(ctx->st, 0, NULL);
ctx->st->destroy(ctx->st);
/* Also frees ctx->pipe?
*/
st_destroy_context(ctx->st);
FREE(ctx); FREE(ctx);
} }
@ -121,14 +108,16 @@ dri_destroy_context(__DRIcontext * cPriv)
GLboolean GLboolean
dri_unbind_context(__DRIcontext * cPriv) dri_unbind_context(__DRIcontext * cPriv)
{ {
struct st_api *stapi = dri_get_st_api();
if (cPriv) { if (cPriv) {
struct dri_context *ctx = dri_context(cPriv); struct dri_context *ctx = dri_context(cPriv);
if (--ctx->bind_count == 0) { if (--ctx->bind_count == 0) {
if (ctx->st && ctx->st == st_get_current()) { if (ctx->st == stapi->get_current(stapi)) {
st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL); ctx->st->flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL);
st_make_current(NULL, NULL, NULL, NULL); stapi->make_current(stapi, NULL, NULL, NULL);
} }
} }
} }
@ -140,83 +129,47 @@ dri_make_current(__DRIcontext * cPriv,
__DRIdrawable * driDrawPriv, __DRIdrawable * driDrawPriv,
__DRIdrawable * driReadPriv) __DRIdrawable * driReadPriv)
{ {
struct st_api *stapi = dri_get_st_api();
if (cPriv) { if (cPriv) {
struct dri_context *ctx = dri_context(cPriv); struct dri_context *ctx = dri_context(cPriv);
struct dri_drawable *draw = dri_drawable(driDrawPriv); struct dri_drawable *draw = dri_drawable(driDrawPriv);
struct dri_drawable *read = dri_drawable(driReadPriv); struct dri_drawable *read = dri_drawable(driReadPriv);
struct st_context *old_st = st_get_current(); struct st_context_iface *old_st;
old_st = stapi->get_current(stapi);
if (old_st && old_st != ctx->st) if (old_st && old_st != ctx->st)
st_flush(old_st, PIPE_FLUSH_RENDER_CACHE, NULL); ctx->st->flush(old_st, PIPE_FLUSH_RENDER_CACHE, NULL);
++ctx->bind_count; ++ctx->bind_count;
if (ctx->dPriv != driDrawPriv) { if (ctx->dPriv != driDrawPriv) {
ctx->dPriv = driDrawPriv; ctx->dPriv = driDrawPriv;
ctx->d_stamp = driDrawPriv->lastStamp - 1; draw->texture_stamp = driDrawPriv->lastStamp - 1;
} }
if (ctx->rPriv != driReadPriv) { if (ctx->rPriv != driReadPriv) {
ctx->rPriv = driReadPriv; ctx->rPriv = driReadPriv;
ctx->r_stamp = driReadPriv->lastStamp - 1; read->texture_stamp = driReadPriv->lastStamp - 1;
} }
/* DRI co-state tracker currently overrides flush_frontbuffer. stapi->make_current(stapi, ctx->st, draw->stfb, read->stfb);
* When this is fixed, will need to pass the drawable in the }
* fourth parameter here so that when Mesa calls else {
* flush_frontbuffer directly (in front-buffer rendering), it stapi->make_current(stapi, NULL, NULL, NULL);
* will have access to the drawable argument:
*/
st_make_current(ctx->st, draw->stfb, read->stfb, ctx);
if (__dri1_api_hooks) {
dri1_update_drawables(ctx, draw, read);
} else {
dri_update_buffer(ctx->pipe->screen,
ctx->pipe->priv);
}
} else {
st_make_current(NULL, NULL, NULL, NULL);
} }
return GL_TRUE; return GL_TRUE;
} }
static void struct dri_context *
st_dri_lock(struct pipe_context *pipe) dri_get_current(void)
{ {
dri_lock((struct dri_context *)pipe->priv); struct st_api *stapi = dri_get_st_api();
} struct st_context_iface *st;
static void st = stapi->get_current(stapi);
st_dri_unlock(struct pipe_context *pipe)
{
dri_unlock((struct dri_context *)pipe->priv);
}
static boolean return (struct dri_context *) (st) ? st->st_manager_private : NULL;
st_dri_is_locked(struct pipe_context *pipe)
{
return ((struct dri_context *)pipe->priv)->isLocked;
} }
static boolean
st_dri_lost_lock(struct pipe_context *pipe)
{
return ((struct dri_context *)pipe->priv)->wsLostLock;
}
static void
st_dri_clear_lost_lock(struct pipe_context *pipe)
{
((struct dri_context *)pipe->priv)->wsLostLock = FALSE;
}
struct dri1_api_lock_funcs dri1_lf = {
.lock = st_dri_lock,
.unlock = st_dri_unlock,
.is_locked = st_dri_is_locked,
.is_lock_lost = st_dri_lost_lock,
.clear_lost_lock = st_dri_clear_lost_lock
};
/* vim: set sw=3 ts=8 sts=3 expandtab: */ /* vim: set sw=3 ts=8 sts=3 expandtab: */

View file

@ -51,9 +51,6 @@ struct dri_context
driOptionCache optionCache; driOptionCache optionCache;
unsigned int d_stamp;
unsigned int r_stamp;
drmLock *lock; drmLock *lock;
boolean isLocked; boolean isLocked;
boolean stLostLock; boolean stLostLock;
@ -62,8 +59,7 @@ struct dri_context
unsigned int bind_count; unsigned int bind_count;
/* gallium */ /* gallium */
struct st_context *st; struct st_context_iface *st;
struct pipe_context *pipe;
}; };
static INLINE struct dri_context * static INLINE struct dri_context *
@ -72,33 +68,9 @@ dri_context(__DRIcontext * driContextPriv)
return (struct dri_context *)driContextPriv->driverPrivate; return (struct dri_context *)driContextPriv->driverPrivate;
} }
static INLINE void
dri_lock(struct dri_context *ctx)
{
drm_context_t hw_context = ctx->cPriv->hHWContext;
char ret = 0;
DRM_CAS(ctx->lock, hw_context, DRM_LOCK_HELD | hw_context, ret);
if (ret) {
drmGetLock(ctx->sPriv->fd, hw_context, 0);
ctx->stLostLock = TRUE;
ctx->wsLostLock = TRUE;
}
ctx->isLocked = TRUE;
}
static INLINE void
dri_unlock(struct dri_context *ctx)
{
ctx->isLocked = FALSE;
DRM_UNLOCK(ctx->sPriv->fd, ctx->lock, ctx->cPriv->hHWContext);
}
/*********************************************************************** /***********************************************************************
* dri_context.c * dri_context.c
*/ */
extern struct dri1_api_lock_funcs dri1_lf;
void dri_destroy_context(__DRIcontext * driContextPriv); void dri_destroy_context(__DRIcontext * driContextPriv);
boolean dri_unbind_context(__DRIcontext * driContextPriv); boolean dri_unbind_context(__DRIcontext * driContextPriv);
@ -108,6 +80,9 @@ dri_make_current(__DRIcontext * driContextPriv,
__DRIdrawable * driDrawPriv, __DRIdrawable * driDrawPriv,
__DRIdrawable * driReadPriv); __DRIdrawable * driReadPriv);
struct dri_context *
dri_get_current(void);
boolean boolean
dri_create_context(const __GLcontextModes * visual, dri_create_context(const __GLcontextModes * visual,
__DRIcontext * driContextPriv, __DRIcontext * driContextPriv,

View file

@ -32,251 +32,30 @@
#include "dri_screen.h" #include "dri_screen.h"
#include "dri_context.h" #include "dri_context.h"
#include "dri_drawable.h" #include "dri_drawable.h"
#include "dri_st_api.h"
#include "dri1.h"
#include "pipe/p_context.h"
#include "pipe/p_screen.h" #include "pipe/p_screen.h"
#include "main/mtypes.h"
#include "main/renderbuffer.h"
#include "state_tracker/drm_api.h"
#include "state_tracker/dri1_api.h"
#include "state_tracker/st_context.h"
#include "state_tracker/st_public.h"
#include "state_tracker/st_cb_fbo.h"
#include "util/u_format.h" #include "util/u_format.h"
#include "util/u_memory.h" #include "util/u_memory.h"
#include "util/u_rect.h"
#include "util/u_inlines.h" #include "util/u_inlines.h"
static struct pipe_surface *
dri_surface_from_handle(struct drm_api *api,
struct pipe_screen *screen,
unsigned handle,
enum pipe_format format,
unsigned width, unsigned height, unsigned pitch)
{
struct pipe_surface *surface = NULL;
struct pipe_texture *texture = NULL;
struct pipe_texture templat;
struct winsys_handle whandle;
memset(&templat, 0, sizeof(templat));
templat.tex_usage |= PIPE_TEXTURE_USAGE_RENDER_TARGET;
templat.target = PIPE_TEXTURE_2D;
templat.last_level = 0;
templat.depth0 = 1;
templat.format = format;
templat.width0 = width;
templat.height0 = height;
memset(&whandle, 0, sizeof(whandle));
whandle.handle = handle;
whandle.stride = pitch;
texture = screen->texture_from_handle(screen, &templat, &whandle);
if (!texture) {
debug_printf("%s: Failed to blanket the buffer with a texture\n", __func__);
return NULL;
}
surface = screen->get_tex_surface(screen, texture, 0, 0, 0,
PIPE_BUFFER_USAGE_GPU_READ |
PIPE_BUFFER_USAGE_GPU_WRITE);
/* we don't need the texture from this point on */
pipe_texture_reference(&texture, NULL);
return surface;
}
/**
* Pixmaps have will have the same name of fake front and front.
*/
static boolean
dri2_check_if_pixmap(__DRIbuffer *buffers, int count)
{
boolean found = FALSE;
boolean is_pixmap = FALSE;
unsigned name;
int i;
for (i = 0; i < count; i++) {
switch (buffers[i].attachment) {
case __DRI_BUFFER_FRONT_LEFT:
case __DRI_BUFFER_FAKE_FRONT_LEFT:
if (found) {
is_pixmap = buffers[i].name == name;
} else {
name = buffers[i].name;
found = TRUE;
}
default:
continue;
}
}
return is_pixmap;
}
/**
* This will be called a drawable is known to have been resized.
*/
void
dri_get_buffers(__DRIdrawable * dPriv)
{
struct dri_drawable *drawable = dri_drawable(dPriv);
struct pipe_surface *surface = NULL;
struct dri_screen *st_screen = dri_screen(drawable->sPriv);
struct pipe_screen *screen = st_screen->pipe_screen;
__DRIbuffer *buffers = NULL;
__DRIscreen *dri_screen = drawable->sPriv;
__DRIdrawable *dri_drawable = drawable->dPriv;
struct drm_api *api = st_screen->api;
boolean have_depth = FALSE;
int i, count;
if ((dri_screen->dri2.loader
&& (dri_screen->dri2.loader->base.version > 2)
&& (dri_screen->dri2.loader->getBuffersWithFormat != NULL))) {
buffers = (*dri_screen->dri2.loader->getBuffersWithFormat)
(dri_drawable, &dri_drawable->w, &dri_drawable->h,
drawable->attachments, drawable->num_attachments,
&count, dri_drawable->loaderPrivate);
} else {
assert(dri_screen->dri2.loader);
buffers = (*dri_screen->dri2.loader->getBuffers) (dri_drawable,
&dri_drawable->w,
&dri_drawable->h,
drawable->attachments,
drawable->
num_attachments, &count,
dri_drawable->
loaderPrivate);
}
if (buffers == NULL) {
return;
}
/* set one cliprect to cover the whole dri_drawable */
dri_drawable->x = 0;
dri_drawable->y = 0;
dri_drawable->backX = 0;
dri_drawable->backY = 0;
dri_drawable->numClipRects = 1;
dri_drawable->pClipRects[0].x1 = 0;
dri_drawable->pClipRects[0].y1 = 0;
dri_drawable->pClipRects[0].x2 = dri_drawable->w;
dri_drawable->pClipRects[0].y2 = dri_drawable->h;
dri_drawable->numBackClipRects = 1;
dri_drawable->pBackClipRects[0].x1 = 0;
dri_drawable->pBackClipRects[0].y1 = 0;
dri_drawable->pBackClipRects[0].x2 = dri_drawable->w;
dri_drawable->pBackClipRects[0].y2 = dri_drawable->h;
if (drawable->old_num == count &&
drawable->old_w == dri_drawable->w &&
drawable->old_h == dri_drawable->h &&
memcmp(drawable->old, buffers, sizeof(__DRIbuffer) * count) == 0) {
return;
} else {
drawable->old_num = count;
drawable->old_w = dri_drawable->w;
drawable->old_h = dri_drawable->h;
memcpy(drawable->old, buffers, sizeof(__DRIbuffer) * count);
}
drawable->is_pixmap = dri2_check_if_pixmap(buffers, count);
for (i = 0; i < count; i++) {
enum pipe_format format = 0;
int index = 0;
switch (buffers[i].attachment) {
case __DRI_BUFFER_FRONT_LEFT:
if (!st_screen->auto_fake_front)
continue;
/* fallthrough */
case __DRI_BUFFER_FAKE_FRONT_LEFT:
index = ST_SURFACE_FRONT_LEFT;
format = drawable->color_format;
break;
case __DRI_BUFFER_BACK_LEFT:
index = ST_SURFACE_BACK_LEFT;
format = drawable->color_format;
break;
case __DRI_BUFFER_DEPTH:
case __DRI_BUFFER_DEPTH_STENCIL:
case __DRI_BUFFER_STENCIL:
index = ST_SURFACE_DEPTH;
format = drawable->depth_stencil_format;
break;
case __DRI_BUFFER_ACCUM:
default:
assert(0);
}
if (index == ST_SURFACE_DEPTH) {
if (have_depth)
continue;
else
have_depth = TRUE;
}
surface = dri_surface_from_handle(api,
screen,
buffers[i].name,
format,
dri_drawable->w,
dri_drawable->h, buffers[i].pitch);
switch (buffers[i].attachment) {
case __DRI_BUFFER_FRONT_LEFT:
case __DRI_BUFFER_FAKE_FRONT_LEFT:
case __DRI_BUFFER_BACK_LEFT:
drawable->color_format = surface->format;
break;
case __DRI_BUFFER_DEPTH:
case __DRI_BUFFER_DEPTH_STENCIL:
case __DRI_BUFFER_STENCIL:
drawable->depth_stencil_format = surface->format;
break;
case __DRI_BUFFER_ACCUM:
default:
assert(0);
}
st_set_framebuffer_surface(drawable->stfb, index, surface);
pipe_surface_reference(&surface, NULL);
}
/* this needed, or else the state tracker fails to pick the new buffers */
st_resize_framebuffer(drawable->stfb, dri_drawable->w, dri_drawable->h);
}
/** /**
* These are used for GLX_EXT_texture_from_pixmap * These are used for GLX_EXT_texture_from_pixmap
*/ */
void dri2_set_tex_buffer2(__DRIcontext *pDRICtx, GLint target, void dri2_set_tex_buffer2(__DRIcontext *pDRICtx, GLint target,
GLint format, __DRIdrawable *dPriv) GLint format, __DRIdrawable *dPriv)
{ {
struct dri_context *ctx = dri_context(pDRICtx);
struct dri_drawable *drawable = dri_drawable(dPriv); struct dri_drawable *drawable = dri_drawable(dPriv);
struct pipe_surface *ps; struct pipe_texture *pt =
dri_get_st_framebuffer_texture(drawable->stfb, ST_ATTACHMENT_FRONT_LEFT);
if (!drawable->stfb->Base.Attachment[BUFFER_FRONT_LEFT].Renderbuffer) { if (pt) {
struct gl_renderbuffer *rb = ctx->st->teximage(ctx->st,
st_new_renderbuffer_fb(drawable->color_format, 0 /*XXX*/, FALSE); (target == GL_TEXTURE_2D) ? ST_TEXTURE_2D : ST_TEXTURE_RECT,
_mesa_add_renderbuffer(&drawable->stfb->Base, BUFFER_FRONT_LEFT, rb); 0, drawable->stvis.color_format, pt, FALSE);
} }
dri_get_buffers(drawable->dPriv);
st_get_framebuffer_surface(drawable->stfb, ST_SURFACE_FRONT_LEFT, &ps);
if (!ps)
return;
st_bind_texture_surface(ps, target == GL_TEXTURE_2D ? ST_TEXTURE_2D :
ST_TEXTURE_RECT, 0, drawable->color_format);
} }
void dri2_set_tex_buffer(__DRIcontext *pDRICtx, GLint target, void dri2_set_tex_buffer(__DRIcontext *pDRICtx, GLint target,
@ -285,53 +64,6 @@ void dri2_set_tex_buffer(__DRIcontext *pDRICtx, GLint target,
dri2_set_tex_buffer2(pDRICtx, target, __DRI_TEXTURE_FORMAT_RGBA, dPriv); dri2_set_tex_buffer2(pDRICtx, target, __DRI_TEXTURE_FORMAT_RGBA, dPriv);
} }
void
dri_update_buffer(struct pipe_screen *screen, void *context_private)
{
struct dri_context *ctx = (struct dri_context *)context_private;
if (ctx->d_stamp == *ctx->dPriv->pStamp &&
ctx->r_stamp == *ctx->rPriv->pStamp)
return;
ctx->d_stamp = *ctx->dPriv->pStamp;
ctx->r_stamp = *ctx->rPriv->pStamp;
/* Ask the X server for new renderbuffers. */
dri_get_buffers(ctx->dPriv);
if (ctx->dPriv != ctx->rPriv)
dri_get_buffers(ctx->rPriv);
}
void
dri_flush_frontbuffer(struct pipe_screen *screen,
struct pipe_surface *surf, void *context_private)
{
struct dri_context *ctx = (struct dri_context *)context_private;
struct dri_drawable *drawable = dri_drawable(ctx->dPriv);
__DRIdrawable *dri_drawable = ctx->dPriv;
__DRIscreen *dri_screen = ctx->sPriv;
/* XXX Does this function get called with DRI1? */
if (ctx->dPriv == NULL) {
debug_printf("%s: no drawable bound to context\n", __func__);
return;
}
#if 0
/* TODO if rendering to pixmaps is slow enable this code. */
if (drawable->is_pixmap)
return;
#else
(void)drawable;
#endif
(*dri_screen->dri2.loader->flushFrontBuffer)(dri_drawable,
dri_drawable->loaderPrivate);
}
/** /**
* This is called when we need to set up GL rendering to a new X window. * This is called when we need to set up GL rendering to a new X window.
*/ */
@ -342,7 +74,6 @@ dri_create_buffer(__DRIscreen * sPriv,
{ {
struct dri_screen *screen = sPriv->private; struct dri_screen *screen = sPriv->private;
struct dri_drawable *drawable = NULL; struct dri_drawable *drawable = NULL;
int i;
if (isPixmap) if (isPixmap)
goto fail; /* not implemented */ goto fail; /* not implemented */
@ -351,45 +82,8 @@ dri_create_buffer(__DRIscreen * sPriv,
if (drawable == NULL) if (drawable == NULL)
goto fail; goto fail;
if (visual->redBits == 8) { dri_fill_st_visual(&drawable->stvis, screen, visual);
if (visual->alphaBits == 8) drawable->stfb = dri_create_st_framebuffer(drawable);
drawable->color_format = PIPE_FORMAT_B8G8R8A8_UNORM;
else
drawable->color_format = PIPE_FORMAT_B8G8R8X8_UNORM;
} else {
drawable->color_format = PIPE_FORMAT_B5G6R5_UNORM;
}
switch(visual->depthBits) {
default:
case 0:
drawable->depth_stencil_format = PIPE_FORMAT_NONE;
break;
case 16:
drawable->depth_stencil_format = PIPE_FORMAT_Z16_UNORM;
break;
case 24:
if (visual->stencilBits == 0) {
drawable->depth_stencil_format = (screen->d_depth_bits_last) ?
PIPE_FORMAT_Z24X8_UNORM:
PIPE_FORMAT_X8Z24_UNORM;
} else {
drawable->depth_stencil_format = (screen->sd_depth_bits_last) ?
PIPE_FORMAT_Z24S8_UNORM:
PIPE_FORMAT_S8Z24_UNORM;
}
break;
case 32:
drawable->depth_stencil_format = PIPE_FORMAT_Z32_UNORM;
break;
}
drawable->stfb = st_create_framebuffer(visual,
drawable->color_format,
drawable->depth_stencil_format,
drawable->depth_stencil_format,
dPriv->w,
dPriv->h, (void *)drawable);
if (drawable->stfb == NULL) if (drawable->stfb == NULL)
goto fail; goto fail;
@ -397,48 +91,6 @@ dri_create_buffer(__DRIscreen * sPriv,
drawable->dPriv = dPriv; drawable->dPriv = dPriv;
dPriv->driverPrivate = (void *)drawable; dPriv->driverPrivate = (void *)drawable;
/* setup dri2 buffers information */
/* TODO incase of double buffer visual, delay fake creation */
i = 0;
if (sPriv->dri2.loader
&& (sPriv->dri2.loader->base.version > 2)
&& (sPriv->dri2.loader->getBuffersWithFormat != NULL)) {
drawable->attachments[i++] = __DRI_BUFFER_FRONT_LEFT;
drawable->attachments[i++] = visual->rgbBits;
if (!screen->auto_fake_front) {
drawable->attachments[i++] = __DRI_BUFFER_FAKE_FRONT_LEFT;
drawable->attachments[i++] = visual->rgbBits;
}
if (visual->doubleBufferMode) {
drawable->attachments[i++] = __DRI_BUFFER_BACK_LEFT;
drawable->attachments[i++] = visual->rgbBits;
}
if (visual->depthBits && visual->stencilBits) {
drawable->attachments[i++] = __DRI_BUFFER_DEPTH_STENCIL;
drawable->attachments[i++] = visual->depthBits + visual->stencilBits;
} else if (visual->depthBits) {
drawable->attachments[i++] = __DRI_BUFFER_DEPTH;
drawable->attachments[i++] = visual->depthBits;
} else if (visual->stencilBits) {
drawable->attachments[i++] = __DRI_BUFFER_STENCIL;
drawable->attachments[i++] = visual->stencilBits;
}
drawable->num_attachments = i / 2;
} else {
drawable->attachments[i++] = __DRI_BUFFER_FRONT_LEFT;
if (!screen->auto_fake_front)
drawable->attachments[i++] = __DRI_BUFFER_FAKE_FRONT_LEFT;
if (visual->doubleBufferMode)
drawable->attachments[i++] = __DRI_BUFFER_BACK_LEFT;
if (visual->depthBits && visual->stencilBits)
drawable->attachments[i++] = __DRI_BUFFER_DEPTH_STENCIL;
else if (visual->depthBits)
drawable->attachments[i++] = __DRI_BUFFER_DEPTH;
else if (visual->stencilBits)
drawable->attachments[i++] = __DRI_BUFFER_STENCIL;
drawable->num_attachments = i;
}
drawable->desired_fences = 2; drawable->desired_fences = 2;
return GL_TRUE; return GL_TRUE;
@ -447,319 +99,23 @@ fail:
return GL_FALSE; return GL_FALSE;
} }
static struct pipe_fence_handle *
dri_swap_fences_pop_front(struct dri_drawable *draw)
{
struct pipe_screen *screen = dri_screen(draw->sPriv)->pipe_screen;
struct pipe_fence_handle *fence = NULL;
if (draw->cur_fences >= draw->desired_fences) {
screen->fence_reference(screen, &fence, draw->swap_fences[draw->tail]);
screen->fence_reference(screen, &draw->swap_fences[draw->tail++], NULL);
--draw->cur_fences;
draw->tail &= DRI_SWAP_FENCES_MASK;
}
return fence;
}
static void
dri_swap_fences_push_back(struct dri_drawable *draw,
struct pipe_fence_handle *fence)
{
struct pipe_screen *screen = dri_screen(draw->sPriv)->pipe_screen;
if (!fence)
return;
if (draw->cur_fences < DRI_SWAP_FENCES_MAX) {
draw->cur_fences++;
screen->fence_reference(screen, &draw->swap_fences[draw->head++],
fence);
draw->head &= DRI_SWAP_FENCES_MASK;
}
}
void void
dri_destroy_buffer(__DRIdrawable * dPriv) dri_destroy_buffer(__DRIdrawable * dPriv)
{ {
struct dri_drawable *drawable = dri_drawable(dPriv); struct dri_drawable *drawable = dri_drawable(dPriv);
struct pipe_fence_handle *fence; int i;
struct pipe_screen *screen = dri_screen(drawable->sPriv)->pipe_screen;
dri1_swap_fences_clear(drawable);
pipe_surface_reference(&drawable->dri1_surface, NULL);
for (i = 0; i < ST_ATTACHMENT_COUNT; i++)
pipe_texture_reference(&drawable->textures[i], NULL);
dri_destroy_st_framebuffer(drawable->stfb);
st_unreference_framebuffer(drawable->stfb);
drawable->desired_fences = 0; drawable->desired_fences = 0;
while (drawable->cur_fences) {
fence = dri_swap_fences_pop_front(drawable);
screen->fence_reference(screen, &fence, NULL);
}
FREE(drawable); FREE(drawable);
} }
static void
dri1_update_drawables_locked(struct dri_context *ctx,
__DRIdrawable * driDrawPriv,
__DRIdrawable * driReadPriv)
{
if (ctx->stLostLock) {
ctx->stLostLock = FALSE;
if (driDrawPriv == driReadPriv)
DRI_VALIDATE_DRAWABLE_INFO(ctx->sPriv, driDrawPriv);
else
DRI_VALIDATE_TWO_DRAWABLES_INFO(ctx->sPriv, driDrawPriv,
driReadPriv);
}
}
/**
* This ensures all contexts which bind to a drawable pick up the
* drawable change and signal new buffer state.
* Calling st_resize_framebuffer for each context may seem like overkill,
* but no new buffers will actually be allocated if the dimensions don't
* change.
*/
static void
dri1_propagate_drawable_change(struct dri_context *ctx)
{
__DRIdrawable *dPriv = ctx->dPriv;
__DRIdrawable *rPriv = ctx->rPriv;
boolean flushed = FALSE;
if (dPriv && ctx->d_stamp != dPriv->lastStamp) {
st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL);
flushed = TRUE;
ctx->d_stamp = dPriv->lastStamp;
st_resize_framebuffer(dri_drawable(dPriv)->stfb, dPriv->w, dPriv->h);
}
if (rPriv && dPriv != rPriv && ctx->r_stamp != rPriv->lastStamp) {
if (!flushed)
st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL);
ctx->r_stamp = rPriv->lastStamp;
st_resize_framebuffer(dri_drawable(rPriv)->stfb, rPriv->w, rPriv->h);
} else if (rPriv && dPriv == rPriv) {
ctx->r_stamp = ctx->d_stamp;
}
}
void
dri1_update_drawables(struct dri_context *ctx,
struct dri_drawable *draw, struct dri_drawable *read)
{
dri_lock(ctx);
dri1_update_drawables_locked(ctx, draw->dPriv, read->dPriv);
dri_unlock(ctx);
dri1_propagate_drawable_change(ctx);
}
static INLINE boolean
dri1_intersect_src_bbox(struct drm_clip_rect *dst,
int dst_x,
int dst_y,
const struct drm_clip_rect *src,
const struct drm_clip_rect *bbox)
{
int xy1;
int xy2;
xy1 = ((int)src->x1 > (int)bbox->x1 + dst_x) ? src->x1 :
(int)bbox->x1 + dst_x;
xy2 = ((int)src->x2 < (int)bbox->x2 + dst_x) ? src->x2 :
(int)bbox->x2 + dst_x;
if (xy1 >= xy2 || xy1 < 0)
return FALSE;
dst->x1 = xy1;
dst->x2 = xy2;
xy1 = ((int)src->y1 > (int)bbox->y1 + dst_y) ? src->y1 :
(int)bbox->y1 + dst_y;
xy2 = ((int)src->y2 < (int)bbox->y2 + dst_y) ? src->y2 :
(int)bbox->y2 + dst_y;
if (xy1 >= xy2 || xy1 < 0)
return FALSE;
dst->y1 = xy1;
dst->y2 = xy2;
return TRUE;
}
static void
dri1_swap_copy(struct dri_context *ctx,
struct pipe_surface *dst,
struct pipe_surface *src,
__DRIdrawable * dPriv, const struct drm_clip_rect *bbox)
{
struct pipe_context *pipe = ctx->pipe;
struct drm_clip_rect clip;
struct drm_clip_rect *cur;
int i;
cur = dPriv->pClipRects;
for (i = 0; i < dPriv->numClipRects; ++i) {
if (dri1_intersect_src_bbox(&clip, dPriv->x, dPriv->y, cur++, bbox)) {
if (pipe->surface_copy) {
pipe->surface_copy(pipe, dst, clip.x1, clip.y1,
src,
(int)clip.x1 - dPriv->x,
(int)clip.y1 - dPriv->y,
clip.x2 - clip.x1, clip.y2 - clip.y1);
} else {
util_surface_copy(pipe, FALSE, dst, clip.x1, clip.y1,
src,
(int)clip.x1 - dPriv->x,
(int)clip.y1 - dPriv->y,
clip.x2 - clip.x1, clip.y2 - clip.y1);
}
}
}
}
static void
dri1_copy_to_front(struct dri_context *ctx,
struct pipe_surface *surf,
__DRIdrawable * dPriv,
const struct drm_clip_rect *sub_box,
struct pipe_fence_handle **fence)
{
struct pipe_context *pipe = ctx->pipe;
boolean save_lost_lock;
uint cur_w;
uint cur_h;
struct drm_clip_rect bbox;
boolean visible = TRUE;
*fence = NULL;
dri_lock(ctx);
save_lost_lock = ctx->stLostLock;
dri1_update_drawables_locked(ctx, dPriv, dPriv);
st_get_framebuffer_dimensions(dri_drawable(dPriv)->stfb, &cur_w, &cur_h);
bbox.x1 = 0;
bbox.x2 = cur_w;
bbox.y1 = 0;
bbox.y2 = cur_h;
if (sub_box)
visible = dri1_intersect_src_bbox(&bbox, 0, 0, &bbox, sub_box);
if (visible && __dri1_api_hooks->present_locked) {
__dri1_api_hooks->present_locked(pipe,
surf,
dPriv->pClipRects,
dPriv->numClipRects,
dPriv->x, dPriv->y, &bbox, fence);
} else if (visible && __dri1_api_hooks->front_srf_locked) {
struct pipe_surface *front = __dri1_api_hooks->front_srf_locked(pipe);
if (front)
dri1_swap_copy(ctx, front, surf, dPriv, &bbox);
st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, fence);
}
ctx->stLostLock = save_lost_lock;
/**
* FIXME: Revisit this: Update drawables on copy_sub_buffer ?
*/
if (!sub_box)
dri1_update_drawables_locked(ctx, ctx->dPriv, ctx->rPriv);
dri_unlock(ctx);
dri1_propagate_drawable_change(ctx);
}
void
dri1_flush_frontbuffer(struct pipe_screen *screen,
struct pipe_surface *surf, void *context_private)
{
struct dri_context *ctx = (struct dri_context *)context_private;
struct pipe_fence_handle *dummy_fence;
dri1_copy_to_front(ctx, surf, ctx->dPriv, NULL, &dummy_fence);
screen->fence_reference(screen, &dummy_fence, NULL);
/**
* FIXME: Do we need swap throttling here?
*/
}
void
dri_swap_buffers(__DRIdrawable * dPriv)
{
struct dri_context *ctx;
struct pipe_surface *back_surf;
struct dri_drawable *draw = dri_drawable(dPriv);
struct pipe_screen *screen = dri_screen(draw->sPriv)->pipe_screen;
struct pipe_fence_handle *fence;
struct st_context *st = st_get_current();
assert(__dri1_api_hooks != NULL);
if (!st)
return; /* For now */
ctx = (struct dri_context *)st->pipe->priv;
st_get_framebuffer_surface(draw->stfb, ST_SURFACE_BACK_LEFT, &back_surf);
if (back_surf) {
st_notify_swapbuffers(draw->stfb);
st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL);
fence = dri_swap_fences_pop_front(draw);
if (fence) {
(void)screen->fence_finish(screen, fence, 0);
screen->fence_reference(screen, &fence, NULL);
}
dri1_copy_to_front(ctx, back_surf, dPriv, NULL, &fence);
dri_swap_fences_push_back(draw, fence);
screen->fence_reference(screen, &fence, NULL);
}
}
void
dri_copy_sub_buffer(__DRIdrawable * dPriv, int x, int y, int w, int h)
{
struct pipe_screen *screen = dri_screen(dPriv->driScreenPriv)->pipe_screen;
struct drm_clip_rect sub_bbox;
struct dri_context *ctx;
struct pipe_surface *back_surf;
struct dri_drawable *draw = dri_drawable(dPriv);
struct pipe_fence_handle *dummy_fence;
struct st_context *st = st_get_current();
assert(__dri1_api_hooks != NULL);
if (!st)
return;
ctx = (struct dri_context *)st->pipe->priv;
sub_bbox.x1 = x;
sub_bbox.x2 = x + w;
sub_bbox.y1 = y;
sub_bbox.y2 = y + h;
st_get_framebuffer_surface(draw->stfb, ST_SURFACE_BACK_LEFT, &back_surf);
if (back_surf) {
st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL);
dri1_copy_to_front(ctx, back_surf, dPriv, &sub_bbox, &dummy_fence);
screen->fence_reference(screen, &dummy_fence, NULL);
}
}
/* vim: set sw=3 ts=8 sts=3 expandtab: */ /* vim: set sw=3 ts=8 sts=3 expandtab: */

View file

@ -29,6 +29,8 @@
#define DRI_DRAWABLE_H #define DRI_DRAWABLE_H
#include "pipe/p_compiler.h" #include "pipe/p_compiler.h"
#include "pipe/p_format.h"
#include "state_tracker/st_api.h"
struct pipe_surface; struct pipe_surface;
struct pipe_fence_handle; struct pipe_fence_handle;
@ -44,26 +46,26 @@ struct dri_drawable
__DRIdrawable *dPriv; __DRIdrawable *dPriv;
__DRIscreen *sPriv; __DRIscreen *sPriv;
unsigned attachments[8]; /* gallium */
unsigned num_attachments; struct st_framebuffer_iface *stfb;
struct st_visual stvis;
boolean is_pixmap;
__DRIbuffer old[8]; __DRIbuffer old[8];
unsigned old_num; unsigned old_num;
unsigned old_w; unsigned old_w;
unsigned old_h; unsigned old_h;
/* gallium */ struct pipe_texture *textures[ST_ATTACHMENT_COUNT];
struct st_framebuffer *stfb; unsigned int texture_mask, texture_stamp;
struct pipe_fence_handle *swap_fences[DRI_SWAP_FENCES_MAX]; struct pipe_fence_handle *swap_fences[DRI_SWAP_FENCES_MAX];
unsigned int head; unsigned int head;
unsigned int tail; unsigned int tail;
unsigned int desired_fences; unsigned int desired_fences;
unsigned int cur_fences; unsigned int cur_fences;
enum pipe_format color_format; /* used only by DRI1 */
enum pipe_format depth_stencil_format; struct pipe_surface *dri1_surface;
}; };
static INLINE struct dri_drawable * static INLINE struct dri_drawable *
@ -80,20 +82,6 @@ dri_create_buffer(__DRIscreen * sPriv,
__DRIdrawable * dPriv, __DRIdrawable * dPriv,
const __GLcontextModes * visual, boolean isPixmap); const __GLcontextModes * visual, boolean isPixmap);
void
dri_update_buffer(struct pipe_screen *screen, void *context_private);
void
dri_flush_frontbuffer(struct pipe_screen *screen,
struct pipe_surface *surf, void *context_private);
void dri_swap_buffers(__DRIdrawable * dPriv);
void
dri_copy_sub_buffer(__DRIdrawable * dPriv, int x, int y, int w, int h);
void dri_get_buffers(__DRIdrawable * dPriv);
void dri_destroy_buffer(__DRIdrawable * dPriv); void dri_destroy_buffer(__DRIdrawable * dPriv);
void dri2_set_tex_buffer2(__DRIcontext *pDRICtx, GLint target, void dri2_set_tex_buffer2(__DRIcontext *pDRICtx, GLint target,
@ -102,13 +90,6 @@ void dri2_set_tex_buffer2(__DRIcontext *pDRICtx, GLint target,
void dri2_set_tex_buffer(__DRIcontext *pDRICtx, GLint target, void dri2_set_tex_buffer(__DRIcontext *pDRICtx, GLint target,
__DRIdrawable *dPriv); __DRIdrawable *dPriv);
void
dri1_update_drawables(struct dri_context *ctx,
struct dri_drawable *draw, struct dri_drawable *read);
void
dri1_flush_frontbuffer(struct pipe_screen *screen,
struct pipe_surface *surf, void *context_private);
#endif #endif
/* vim: set sw=3 ts=8 sts=3 expandtab: */ /* vim: set sw=3 ts=8 sts=3 expandtab: */

View file

@ -38,9 +38,11 @@
void void
dri_init_extensions(struct dri_context *ctx) dri_init_extensions(struct dri_context *ctx)
{ {
struct st_context *st = (struct st_context *) ctx->st;
/* New extensions should be added in mesa/state_tracker/st_extensions.c /* New extensions should be added in mesa/state_tracker/st_extensions.c
* and not in this file. */ * and not in this file. */
driInitExtensions(ctx->st->ctx, NULL, GL_FALSE); driInitExtensions(st->ctx, NULL, GL_FALSE);
} }
/* vim: set sw=3 ts=8 sts=3 expandtab: */ /* vim: set sw=3 ts=8 sts=3 expandtab: */

View file

@ -36,11 +36,13 @@
#include "dri_screen.h" #include "dri_screen.h"
#include "dri_context.h" #include "dri_context.h"
#include "dri_drawable.h" #include "dri_drawable.h"
#include "dri_st_api.h"
#include "dri1.h"
#include "util/u_inlines.h"
#include "pipe/p_screen.h" #include "pipe/p_screen.h"
#include "pipe/p_format.h" #include "pipe/p_format.h"
#include "state_tracker/drm_api.h" #include "state_tracker/drm_api.h"
#include "state_tracker/dri1_api.h"
#include "util/u_debug.h" #include "util/u_debug.h"
@ -53,7 +55,7 @@ PUBLIC const char __driConfigOptions[] =
DRI_CONF_ALLOW_LARGE_TEXTURES(1) DRI_CONF_ALLOW_LARGE_TEXTURES(1)
DRI_CONF_SECTION_END DRI_CONF_END; DRI_CONF_SECTION_END DRI_CONF_END;
const uint __driNConfigOptions = 3; const uint __driNConfigOptions = 3;
static const __DRItexBufferExtension dri2TexBufferExtension = { static const __DRItexBufferExtension dri2TexBufferExtension = {
{ __DRI_TEX_BUFFER, __DRI_TEX_BUFFER_VERSION }, { __DRI_TEX_BUFFER, __DRI_TEX_BUFFER_VERSION },
@ -66,10 +68,23 @@ dri2_flush_drawable(__DRIdrawable *draw)
{ {
} }
static void
dri2_invalidate_drawable(__DRIdrawable *dPriv)
{
struct dri_drawable *drawable = dri_drawable(dPriv);
struct dri_context *ctx = dri_context(dPriv->driContextPriv);
dri2InvalidateDrawable(dPriv);
drawable->dPriv->lastStamp = *drawable->dPriv->pStamp;
if (ctx)
ctx->st->notify_invalid_framebuffer(ctx->st, drawable->stfb);
}
static const __DRI2flushExtension dri2FlushExtension = { static const __DRI2flushExtension dri2FlushExtension = {
{ __DRI2_FLUSH, __DRI2_FLUSH_VERSION }, { __DRI2_FLUSH, __DRI2_FLUSH_VERSION },
dri2_flush_drawable, dri2_flush_drawable,
dri2InvalidateDrawable, dri2_invalidate_drawable,
}; };
static const __DRIextension *dri_screen_extensions[] = { static const __DRIextension *dri_screen_extensions[] = {
@ -83,9 +98,7 @@ static const __DRI2flushExtension dri2FlushExtension = {
NULL NULL
}; };
struct dri1_api *__dri1_api_hooks = NULL; const __DRIconfig **
static const __DRIconfig **
dri_fill_in_modes(struct dri_screen *screen, dri_fill_in_modes(struct dri_screen *screen,
unsigned pixel_bits) unsigned pixel_bits)
{ {
@ -228,6 +241,68 @@ dri_fill_in_modes(struct dri_screen *screen,
return (const __DRIconfig **)configs; return (const __DRIconfig **)configs;
} }
/**
* Roughly the converse of dri_fill_in_modes.
*/
void
dri_fill_st_visual(struct st_visual *stvis, struct dri_screen *screen,
const __GLcontextModes *mode)
{
memset(stvis, 0, sizeof(*stvis));
stvis->samples = mode->samples;
stvis->render_buffer = ST_ATTACHMENT_INVALID;
if (mode->redBits == 8) {
if (mode->alphaBits == 8)
stvis->color_format = PIPE_FORMAT_B8G8R8A8_UNORM;
else
stvis->color_format = PIPE_FORMAT_B8G8R8X8_UNORM;
} else {
stvis->color_format = PIPE_FORMAT_B5G6R5_UNORM;
}
switch (mode->depthBits) {
default:
case 0:
stvis->depth_stencil_format = PIPE_FORMAT_NONE;
break;
case 16:
stvis->depth_stencil_format = PIPE_FORMAT_Z16_UNORM;
break;
case 24:
if (mode->stencilBits == 0) {
stvis->depth_stencil_format = (screen->d_depth_bits_last) ?
PIPE_FORMAT_Z24X8_UNORM:
PIPE_FORMAT_X8Z24_UNORM;
} else {
stvis->depth_stencil_format = (screen->sd_depth_bits_last) ?
PIPE_FORMAT_Z24S8_UNORM:
PIPE_FORMAT_S8Z24_UNORM;
}
break;
case 32:
stvis->depth_stencil_format = PIPE_FORMAT_Z32_UNORM;
break;
}
stvis->accum_format = (mode->haveAccumBuffer) ?
PIPE_FORMAT_R16G16B16A16_SNORM : PIPE_FORMAT_NONE;
stvis->buffer_mask |= ST_ATTACHMENT_FRONT_LEFT_MASK;
if (mode->doubleBufferMode)
stvis->buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK;
if (mode->stereoMode) {
stvis->buffer_mask |= ST_ATTACHMENT_FRONT_RIGHT_MASK;
if (mode->doubleBufferMode)
stvis->buffer_mask |= ST_ATTACHMENT_BACK_RIGHT_MASK;
}
if (mode->haveDepthBuffer || mode->haveStencilBuffer)
stvis->buffer_mask |= ST_ATTACHMENT_DEPTH_STENCIL_MASK;
/* let the state tracker allocate the accum buffer */
}
/** /**
* Get information about previous buffer swaps. * Get information about previous buffer swaps.
*/ */
@ -240,73 +315,31 @@ dri_get_swap_info(__DRIdrawable * dPriv, __DRIswapInfo * sInfo)
return 0; return 0;
} }
static INLINE void static void
dri_copy_version(struct dri1_api_version *dst, dri_destroy_screen(__DRIscreen * sPriv)
const struct __DRIversionRec *src)
{ {
dst->major = src->major; struct dri_screen *screen = dri_screen(sPriv);
dst->minor = src->minor; int i;
dst->patch_level = src->patch;
}
static const __DRIconfig ** if (screen->dri1_pipe)
dri_init_screen(__DRIscreen * sPriv) screen->dri1_pipe->destroy(screen->dri1_pipe);
{
struct dri_screen *screen;
const __DRIconfig **configs;
struct dri1_create_screen_arg arg;
screen = CALLOC_STRUCT(dri_screen); if (screen->smapi)
if (!screen) dri_destroy_st_manager(screen->smapi);
return NULL; if (screen->pipe_screen)
screen->pipe_screen->destroy(screen->pipe_screen);
screen->api = drm_api_create(); for (i = 0; i < (1 << screen->optionCache.tableSize); ++i) {
screen->sPriv = sPriv; FREE(screen->optionCache.info[i].name);
screen->fd = sPriv->fd; FREE(screen->optionCache.info[i].ranges);
screen->drmLock = (drmLock *) & sPriv->pSAREA->lock;
sPriv->private = (void *)screen;
sPriv->extensions = dri_screen_extensions;
arg.base.mode = DRM_CREATE_DRI1;
arg.lf = &dri1_lf;
arg.ddx_info = sPriv->pDevPriv;
arg.ddx_info_size = sPriv->devPrivSize;
arg.sarea = sPriv->pSAREA;
dri_copy_version(&arg.ddx_version, &sPriv->ddx_version);
dri_copy_version(&arg.dri_version, &sPriv->dri_version);
dri_copy_version(&arg.drm_version, &sPriv->drm_version);
arg.api = NULL;
screen->pipe_screen = screen->api->create_screen(screen->api, screen->fd, &arg.base);
if (!screen->pipe_screen || !arg.api) {
debug_printf("%s: failed to create dri1 screen\n", __FUNCTION__);
goto out_no_screen;
} }
__dri1_api_hooks = arg.api; FREE(screen->optionCache.info);
FREE(screen->optionCache.values);
screen->pipe_screen->flush_frontbuffer = dri1_flush_frontbuffer;
driParseOptionInfo(&screen->optionCache,
__driConfigOptions, __driNConfigOptions);
/**
* FIXME: If the driver supports format conversion swapbuffer blits, we might
* want to support other color bit depths than the server is currently
* using.
*/
configs = dri_fill_in_modes(screen, sPriv->fbBPP);
if (!configs)
goto out_no_configs;
return configs;
out_no_configs:
screen->pipe_screen->destroy(screen->pipe_screen);
out_no_screen:
FREE(screen); FREE(screen);
return NULL; sPriv->private = NULL;
sPriv->extensions = NULL;
} }
/** /**
@ -324,7 +357,7 @@ dri_init_screen2(__DRIscreen * sPriv)
screen = CALLOC_STRUCT(dri_screen); screen = CALLOC_STRUCT(dri_screen);
if (!screen) if (!screen)
goto fail; return NULL;
screen->api = drm_api_create(); screen->api = drm_api_create();
screen->sPriv = sPriv; screen->sPriv = sPriv;
@ -339,9 +372,9 @@ dri_init_screen2(__DRIscreen * sPriv)
goto fail; goto fail;
} }
/* We need to hook in here */ screen->smapi = dri_create_st_manager(screen);
screen->pipe_screen->update_buffer = dri_update_buffer; if (!screen->smapi)
screen->pipe_screen->flush_frontbuffer = dri_flush_frontbuffer; goto fail;
driParseOptionInfo(&screen->optionCache, driParseOptionInfo(&screen->optionCache,
__driConfigOptions, __driNConfigOptions); __driConfigOptions, __driNConfigOptions);
@ -350,46 +383,27 @@ dri_init_screen2(__DRIscreen * sPriv)
dri2_ext->getBuffersWithFormat != NULL; dri2_ext->getBuffersWithFormat != NULL;
return dri_fill_in_modes(screen, 32); return dri_fill_in_modes(screen, 32);
fail: fail:
dri_destroy_screen(sPriv);
return NULL; return NULL;
} }
static void const struct __DriverAPIRec driDriverAPI = {
dri_destroy_screen(__DRIscreen * sPriv)
{
struct dri_screen *screen = dri_screen(sPriv);
int i;
screen->pipe_screen->destroy(screen->pipe_screen);
for (i = 0; i < (1 << screen->optionCache.tableSize); ++i) {
FREE(screen->optionCache.info[i].name);
FREE(screen->optionCache.info[i].ranges);
}
FREE(screen->optionCache.info);
FREE(screen->optionCache.values);
FREE(screen);
sPriv->private = NULL;
}
PUBLIC const struct __DriverAPIRec driDriverAPI = {
.InitScreen = dri_init_screen,
.DestroyScreen = dri_destroy_screen, .DestroyScreen = dri_destroy_screen,
.CreateContext = dri_create_context, .CreateContext = dri_create_context,
.DestroyContext = dri_destroy_context, .DestroyContext = dri_destroy_context,
.CreateBuffer = dri_create_buffer, .CreateBuffer = dri_create_buffer,
.DestroyBuffer = dri_destroy_buffer, .DestroyBuffer = dri_destroy_buffer,
.SwapBuffers = dri_swap_buffers,
.MakeCurrent = dri_make_current, .MakeCurrent = dri_make_current,
.UnbindContext = dri_unbind_context, .UnbindContext = dri_unbind_context,
.GetSwapInfo = dri_get_swap_info, .GetSwapInfo = dri_get_swap_info,
.GetDrawableMSC = driDrawableGetMSC32, .GetDrawableMSC = driDrawableGetMSC32,
.WaitForMSC = driWaitForMSC32, .WaitForMSC = driWaitForMSC32,
.CopySubBuffer = dri_copy_sub_buffer,
.InitScreen = dri_init_screen,
.InitScreen2 = dri_init_screen2, .InitScreen2 = dri_init_screen2,
.InitScreen = dri1_init_screen,
.SwapBuffers = dri1_swap_buffers,
.CopySubBuffer = dri1_copy_sub_buffer,
}; };
/* This is the table of extensions that the loader will dlsym() for. */ /* This is the table of extensions that the loader will dlsym() for. */

View file

@ -36,8 +36,9 @@
#include "xmlconfig.h" #include "xmlconfig.h"
#include "pipe/p_compiler.h" #include "pipe/p_compiler.h"
#include "pipe/p_context.h"
#include "state_tracker/dri1_api.h" #include "pipe/p_state.h"
#include "state_tracker/st_api.h"
struct dri_screen struct dri_screen
{ {
@ -60,6 +61,11 @@ struct dri_screen
boolean d_depth_bits_last; boolean d_depth_bits_last;
boolean sd_depth_bits_last; boolean sd_depth_bits_last;
boolean auto_fake_front; boolean auto_fake_front;
struct st_manager *smapi;
/* used only by DRI1 */
struct pipe_context *dri1_pipe;
}; };
/** cast wrapper */ /** cast wrapper */
@ -69,11 +75,14 @@ dri_screen(__DRIscreen * sPriv)
return (struct dri_screen *)sPriv->private; return (struct dri_screen *)sPriv->private;
} }
/*********************************************************************** extern const uint __driNConfigOptions;
* dri_screen.c
*/
extern struct dri1_api *__dri1_api_hooks; const __DRIconfig **
dri_fill_in_modes(struct dri_screen *screen, unsigned pixel_bits);
void
dri_fill_st_visual(struct st_visual *stvis, struct dri_screen *screen,
const __GLcontextModes *mode);
#endif #endif

View file

@ -0,0 +1,445 @@
/*
* Mesa 3-D graphics library
* Version: 7.9
*
* Copyright (C) 2010 LunarG Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Authors:
* Chia-I Wu <olv@lunarg.com>
*/
#include "util/u_memory.h"
#include "util/u_inlines.h"
#include "util/u_format.h"
#include "util/u_debug.h"
#include "state_tracker/drm_api.h"
#include "state_tracker/st_manager.h" /* for st_manager_create_api */
#include "dri_screen.h"
#include "dri_context.h"
#include "dri_drawable.h"
#include "dri_st_api.h"
#include "dri1.h"
static struct {
int32_t refcnt;
struct st_api *stapi;
} dri_st_api;
/**
* Get the format of an attachment.
*/
static INLINE enum pipe_format
dri_drawable_get_format(struct dri_drawable *drawable,
enum st_attachment_type statt)
{
enum pipe_format format;
switch (statt) {
case ST_ATTACHMENT_FRONT_LEFT:
case ST_ATTACHMENT_BACK_LEFT:
case ST_ATTACHMENT_FRONT_RIGHT:
case ST_ATTACHMENT_BACK_RIGHT:
format = drawable->stvis.color_format;
break;
case ST_ATTACHMENT_DEPTH_STENCIL:
format = drawable->stvis.depth_stencil_format;
break;
default:
format = PIPE_FORMAT_NONE;
break;
}
return format;
}
/**
* Process __DRIbuffer and convert them into pipe_textures.
*/
static void
dri_drawable_process_buffers(struct dri_drawable *drawable,
__DRIbuffer *buffers, unsigned count)
{
struct dri_screen *screen = dri_screen(drawable->sPriv);
__DRIdrawable *dri_drawable = drawable->dPriv;
struct pipe_texture templ;
struct winsys_handle whandle;
boolean have_depth = FALSE;
unsigned i;
if (drawable->old_num == count &&
drawable->old_w == dri_drawable->w &&
drawable->old_h == dri_drawable->h &&
memcmp(drawable->old, buffers, sizeof(__DRIbuffer) * count) == 0)
return;
for (i = 0; i < ST_ATTACHMENT_COUNT; i++)
pipe_texture_reference(&drawable->textures[i], NULL);
memset(&templ, 0, sizeof(templ));
templ.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET;
templ.target = PIPE_TEXTURE_2D;
templ.last_level = 0;
templ.width0 = dri_drawable->w;
templ.height0 = dri_drawable->h;
templ.depth0 = 1;
memset(&whandle, 0, sizeof(whandle));
for (i = 0; i < count; i++) {
__DRIbuffer *buf = &buffers[i];
enum st_attachment_type statt;
enum pipe_format format;
switch (buf->attachment) {
case __DRI_BUFFER_FRONT_LEFT:
if (!screen->auto_fake_front) {
statt = ST_ATTACHMENT_INVALID;
break;
}
/* fallthrough */
case __DRI_BUFFER_FAKE_FRONT_LEFT:
statt = ST_ATTACHMENT_FRONT_LEFT;
break;
case __DRI_BUFFER_BACK_LEFT:
statt = ST_ATTACHMENT_BACK_LEFT;
break;
case __DRI_BUFFER_DEPTH:
case __DRI_BUFFER_DEPTH_STENCIL:
case __DRI_BUFFER_STENCIL:
statt = ST_ATTACHMENT_DEPTH_STENCIL;
/* use only the first depth/stencil buffer */
if (have_depth)
statt = ST_ATTACHMENT_INVALID;
else
have_depth = TRUE;
break;
default:
statt = ST_ATTACHMENT_INVALID;
break;
}
format = dri_drawable_get_format(drawable, statt);
if (statt == ST_ATTACHMENT_INVALID || format == PIPE_FORMAT_NONE)
continue;
templ.format = format;
whandle.handle = buf->name;
whandle.stride = buf->pitch;
drawable->textures[statt] =
screen->pipe_screen->texture_from_handle(screen->pipe_screen,
&templ, &whandle);
}
drawable->old_num = count;
drawable->old_w = dri_drawable->w;
drawable->old_h = dri_drawable->h;
memcpy(drawable->old, buffers, sizeof(__DRIbuffer) * count);
}
/**
* Retrieve __DRIbuffer from the DRI loader.
*/
static __DRIbuffer *
dri_drawable_get_buffers(struct dri_drawable *drawable,
const enum st_attachment_type *statts,
unsigned *count)
{
__DRIdrawable *dri_drawable = drawable->dPriv;
struct __DRIdri2LoaderExtensionRec *loader = drawable->sPriv->dri2.loader;
boolean with_format;
__DRIbuffer *buffers;
int num_buffers;
unsigned attachments[8];
unsigned num_attachments, i;
assert(loader);
with_format = (loader->base.version > 2 && loader->getBuffersWithFormat);
num_attachments = 0;
for (i = 0; i < *count; i++) {
enum pipe_format format;
int att;
format = dri_drawable_get_format(drawable, statts[i]);
if (format == PIPE_FORMAT_NONE)
continue;
switch (statts[i]) {
case ST_ATTACHMENT_FRONT_LEFT:
att = __DRI_BUFFER_FRONT_LEFT;
break;
case ST_ATTACHMENT_BACK_LEFT:
att = __DRI_BUFFER_BACK_LEFT;
break;
case ST_ATTACHMENT_FRONT_RIGHT:
att = __DRI_BUFFER_FRONT_RIGHT;
break;
case ST_ATTACHMENT_BACK_RIGHT:
att = __DRI_BUFFER_BACK_RIGHT;
break;
case ST_ATTACHMENT_DEPTH_STENCIL:
att = __DRI_BUFFER_DEPTH_STENCIL;
break;
default:
att = -1;
break;
}
if (att >= 0) {
attachments[num_attachments++] = att;
if (with_format) {
attachments[num_attachments++] =
util_format_get_blocksizebits(format);
}
}
}
if (with_format) {
num_attachments /= 2;
buffers = loader->getBuffersWithFormat(dri_drawable,
&dri_drawable->w, &dri_drawable->h,
attachments, num_attachments,
&num_buffers, dri_drawable->loaderPrivate);
}
else {
buffers = loader->getBuffers(dri_drawable,
&dri_drawable->w, &dri_drawable->h,
attachments, num_attachments,
&num_buffers, dri_drawable->loaderPrivate);
}
if (buffers) {
/* set one cliprect to cover the whole dri_drawable */
dri_drawable->x = 0;
dri_drawable->y = 0;
dri_drawable->backX = 0;
dri_drawable->backY = 0;
dri_drawable->numClipRects = 1;
dri_drawable->pClipRects[0].x1 = 0;
dri_drawable->pClipRects[0].y1 = 0;
dri_drawable->pClipRects[0].x2 = dri_drawable->w;
dri_drawable->pClipRects[0].y2 = dri_drawable->h;
dri_drawable->numBackClipRects = 1;
dri_drawable->pBackClipRects[0].x1 = 0;
dri_drawable->pBackClipRects[0].y1 = 0;
dri_drawable->pBackClipRects[0].x2 = dri_drawable->w;
dri_drawable->pBackClipRects[0].y2 = dri_drawable->h;
*count = num_buffers;
}
return buffers;
}
static boolean
dri_st_framebuffer_validate(struct st_framebuffer_iface *stfbi,
const enum st_attachment_type *statts,
unsigned count,
struct pipe_texture **out)
{
struct dri_drawable *drawable =
(struct dri_drawable *) stfbi->st_manager_private;
unsigned statt_mask, i;
statt_mask = 0x0;
for (i = 0; i < count; i++)
statt_mask |= (1 << statts[i]);
/*
* dPriv->pStamp is the server stamp. It should be accessed with a lock, at
* least for DRI1. dPriv->lastStamp is the client stamp. It has the value
* of the server stamp when last checked.
*
* This function updates the textures and records the stamp of the textures.
*/
if (drawable->texture_stamp != drawable->dPriv->lastStamp ||
(statt_mask & ~drawable->texture_mask)) {
if (__dri1_api_hooks) {
dri1_allocate_textures(drawable,
drawable->dPriv->w, drawable->dPriv->h, statt_mask);
}
else {
__DRIbuffer *buffers;
unsigned num_buffers = count;
buffers = dri_drawable_get_buffers(drawable, statts, &num_buffers);
dri_drawable_process_buffers(drawable, buffers, num_buffers);
}
drawable->texture_stamp = drawable->dPriv->lastStamp;
drawable->texture_mask = statt_mask;
}
if (!out)
return TRUE;
for (i = 0; i < count; i++) {
out[i] = NULL;
pipe_texture_reference(&out[i], drawable->textures[statts[i]]);
}
return TRUE;
}
static boolean
dri_st_framebuffer_flush_front(struct st_framebuffer_iface *stfbi,
enum st_attachment_type statt)
{
struct dri_drawable *drawable =
(struct dri_drawable *) stfbi->st_manager_private;
struct __DRIdri2LoaderExtensionRec *loader =
drawable->sPriv->dri2.loader;
if (__dri1_api_hooks) {
struct pipe_texture *ptex = drawable->textures[statt];
if (ptex)
dri1_flush_frontbuffer(drawable, ptex);
return TRUE;
}
if (statt == ST_ATTACHMENT_FRONT_LEFT && loader->flushFrontBuffer) {
loader->flushFrontBuffer(drawable->dPriv,
drawable->dPriv->loaderPrivate);
}
return TRUE;
}
/**
* Create a framebuffer from the given drawable.
*/
struct st_framebuffer_iface *
dri_create_st_framebuffer(struct dri_drawable *drawable)
{
struct st_framebuffer_iface *stfbi;
stfbi = CALLOC_STRUCT(st_framebuffer_iface);
if (stfbi) {
stfbi->visual = &drawable->stvis;
stfbi->flush_front = dri_st_framebuffer_flush_front;
stfbi->validate = dri_st_framebuffer_validate;
stfbi->st_manager_private = (void *) drawable;
}
return stfbi;
}
/**
* Destroy a framebuffer.
*/
void
dri_destroy_st_framebuffer(struct st_framebuffer_iface *stfbi)
{
FREE(stfbi);
}
/**
* Return the texture at an attachment. Allocate the texture if it does not
* exist.
*/
struct pipe_texture *
dri_get_st_framebuffer_texture(struct st_framebuffer_iface *stfbi,
enum st_attachment_type statt)
{
struct dri_drawable *drawable =
(struct dri_drawable *) stfbi->st_manager_private;
if (!(drawable->texture_mask & (1 << statt))) {
enum st_attachment_type statts[ST_ATTACHMENT_COUNT];
unsigned i, count = 0;
/* make sure DRI2 does not destroy existing buffers */
for (i = 0; i < ST_ATTACHMENT_COUNT; i++) {
if (drawable->texture_mask & (1 << i)) {
statts[count++] = i;
}
}
statts[count++] = statt;
drawable->texture_stamp = drawable->dPriv->lastStamp - 1;
dri_st_framebuffer_validate(stfbi, statts, count, NULL);
}
return drawable->textures[statt];
}
/**
* Add a reference to the st_api of the state tracker.
*/
static void
_dri_get_st_api(void)
{
p_atomic_inc(&dri_st_api.refcnt);
if (p_atomic_read(&dri_st_api.refcnt) == 1)
dri_st_api.stapi = st_manager_create_api();
}
/**
* Remove a reference to the st_api of the state tracker.
*/
static void
_dri_put_st_api(void)
{
struct st_api *stapi = dri_st_api.stapi;
if (p_atomic_dec_zero(&dri_st_api.refcnt)) {
stapi->destroy(dri_st_api.stapi);
dri_st_api.stapi = NULL;
}
}
/**
* Create a state tracker manager from the given screen.
*/
struct st_manager *
dri_create_st_manager(struct dri_screen *screen)
{
struct st_manager *smapi;
smapi = CALLOC_STRUCT(st_manager);
if (smapi) {
smapi->screen = screen->pipe_screen;
_dri_get_st_api();
}
return smapi;
}
/**
* Destroy a state tracker manager.
*/
void
dri_destroy_st_manager(struct st_manager *smapi)
{
_dri_put_st_api();
FREE(smapi);
}
/**
* Return the st_api of OpenGL state tracker.
*/
struct st_api *
dri_get_st_api(void)
{
assert(dri_st_api.stapi);
return dri_st_api.stapi;
}

View file

@ -0,0 +1,55 @@
/*
* Mesa 3-D graphics library
* Version: 7.9
*
* Copyright (C) 2010 LunarG Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Authors:
* Chia-I Wu <olv@lunarg.com>
*/
#ifndef _DRI_ST_API_H_
#define _DRI_ST_API_H_
#include "state_tracker/st_api.h"
struct dri_screen;
struct dri_drawable;
struct st_api *
dri_get_st_api(void);
struct st_manager *
dri_create_st_manager(struct dri_screen *screen);
void
dri_destroy_st_manager(struct st_manager *smapi);
struct st_framebuffer_iface *
dri_create_st_framebuffer(struct dri_drawable *drawable);
void
dri_destroy_st_framebuffer(struct st_framebuffer_iface *stfbi);
struct pipe_texture *
dri_get_st_framebuffer_texture(struct st_framebuffer_iface *stfbi,
enum st_attachment_type statt);
#endif /* _DRI_ST_API_H_ */

View file

@ -553,6 +553,7 @@ st_context_teximage(struct st_context_iface *stctxi, enum st_texture_type target
_mesa_clear_texture_image(ctx, texImage); _mesa_clear_texture_image(ctx, texImage);
} }
stObj->pipe = st->pipe;
pipe_texture_reference(&stImage->pt, tex); pipe_texture_reference(&stImage->pt, tex);
_mesa_dirty_texobj(ctx, texObj, GL_TRUE); _mesa_dirty_texobj(ctx, texObj, GL_TRUE);