mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-01-02 03:00:24 +01:00
Merge branch 'mesa_7_5_branch'
This commit is contained in:
commit
28471cfa97
14 changed files with 380 additions and 181 deletions
|
|
@ -39,6 +39,12 @@
|
|||
#include <GL/gl.h>
|
||||
#include <GL/glx.h>
|
||||
|
||||
#ifndef GLX_MESA_swap_control
|
||||
#define GLX_MESA_swap_control 1
|
||||
typedef int (*PFNGLXGETSWAPINTERVALMESAPROC)(void);
|
||||
#endif
|
||||
|
||||
|
||||
static int is_glx_extension_supported(Display *dpy, const char *query);
|
||||
|
||||
static void query_vsync(Display *dpy);
|
||||
|
|
@ -592,31 +598,22 @@ query_vsync(Display *dpy)
|
|||
int interval = 0;
|
||||
|
||||
|
||||
#ifdef GLX_MESA_swap_control
|
||||
if ((interval <= 0)
|
||||
&& is_glx_extension_supported(dpy, "GLX_MESA_swap_control")) {
|
||||
if (is_glx_extension_supported(dpy, "GLX_MESA_swap_control")) {
|
||||
PFNGLXGETSWAPINTERVALMESAPROC pglXGetSwapIntervalMESA =
|
||||
(PFNGLXGETSWAPINTERVALMESAPROC)
|
||||
glXGetProcAddressARB((const GLubyte *) "glXGetSwapIntervalMESA");
|
||||
|
||||
interval = (*pglXGetSwapIntervalMESA)();
|
||||
} else if (is_glx_extension_supported(dpy, "GLX_SGI_swap_control")) {
|
||||
/* The default swap interval with this extension is 1. Assume that it
|
||||
* is set to the default.
|
||||
*
|
||||
* Many Mesa-based drivers default to 0, but all of these drivers also
|
||||
* export GLX_MESA_swap_control. In that case, this branch will never
|
||||
* be taken, and the correct result should be reported.
|
||||
*/
|
||||
interval = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef GLX_SGI_video_sync
|
||||
if ((interval <= 0)
|
||||
&& is_glx_extension_supported(dpy, "GLX_SGI_video_sync")) {
|
||||
PFNGLXGETVIDEOSYNCSGIPROC pglXGetVideoSyncSGI =
|
||||
(PFNGLXGETVIDEOSYNCSGIPROC)
|
||||
glXGetProcAddressARB((const GLubyte *) "glXGetVideoSyncSGI");
|
||||
unsigned count;
|
||||
|
||||
if ((*pglXGetVideoSyncSGI)(& count) == 0) {
|
||||
interval = (int) count;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
if (interval > 0) {
|
||||
|
|
|
|||
|
|
@ -1202,6 +1202,19 @@ pipe_put_tile_z(struct pipe_transfer *pt,
|
|||
}
|
||||
break;
|
||||
case PIPE_FORMAT_S8Z24_UNORM:
|
||||
{
|
||||
uint *pDest = (uint *) (map + y * pt->stride + x*4);
|
||||
assert(pt->usage == PIPE_TRANSFER_READ_WRITE);
|
||||
for (i = 0; i < h; i++) {
|
||||
for (j = 0; j < w; j++) {
|
||||
/* convert 32-bit Z to 24-bit Z, preserve stencil */
|
||||
pDest[j] = (pDest[j] & 0xff000000) | ptrc[j] >> 8;
|
||||
}
|
||||
pDest += pt->stride/4;
|
||||
ptrc += srcStride;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PIPE_FORMAT_X8Z24_UNORM:
|
||||
{
|
||||
uint *pDest = (uint *) (map + y * pt->stride + x*4);
|
||||
|
|
@ -1216,13 +1229,26 @@ pipe_put_tile_z(struct pipe_transfer *pt,
|
|||
}
|
||||
break;
|
||||
case PIPE_FORMAT_Z24S8_UNORM:
|
||||
{
|
||||
uint *pDest = (uint *) (map + y * pt->stride + x*4);
|
||||
assert(pt->usage == PIPE_TRANSFER_READ_WRITE);
|
||||
for (i = 0; i < h; i++) {
|
||||
for (j = 0; j < w; j++) {
|
||||
/* convert 32-bit Z to 24-bit Z, preserve stencil */
|
||||
pDest[j] = (pDest[j] & 0xff) | (ptrc[j] & 0xffffff00);
|
||||
}
|
||||
pDest += pt->stride/4;
|
||||
ptrc += srcStride;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PIPE_FORMAT_Z24X8_UNORM:
|
||||
{
|
||||
uint *pDest = (uint *) (map + y * pt->stride + x*4);
|
||||
for (i = 0; i < h; i++) {
|
||||
for (j = 0; j < w; j++) {
|
||||
/* convert 32-bit Z to 24-bit Z (0 stencil) */
|
||||
pDest[j] = ptrc[j] << 8;
|
||||
pDest[j] = ptrc[j] & 0xffffff00;
|
||||
}
|
||||
pDest += pt->stride/4;
|
||||
ptrc += srcStride;
|
||||
|
|
|
|||
|
|
@ -60,8 +60,14 @@ stw_context(GLcontext *glctx)
|
|||
static INLINE struct stw_context *
|
||||
stw_current_context(void)
|
||||
{
|
||||
GET_CURRENT_CONTEXT( glctx );
|
||||
return stw_context(glctx);
|
||||
/* We must check if multiple threads are being used or GET_CURRENT_CONTEXT
|
||||
* might return the current context of the thread first seen. */
|
||||
_glapi_check_multithread();
|
||||
|
||||
{
|
||||
GET_CURRENT_CONTEXT( glctx );
|
||||
return stw_context(glctx);
|
||||
}
|
||||
}
|
||||
|
||||
BOOL
|
||||
|
|
@ -74,7 +80,7 @@ stw_copy_context(
|
|||
struct stw_context *dst;
|
||||
BOOL ret = FALSE;
|
||||
|
||||
pipe_mutex_lock( stw_dev->mutex );
|
||||
pipe_mutex_lock( stw_dev->ctx_mutex );
|
||||
|
||||
src = stw_lookup_context_locked( hglrcSrc );
|
||||
dst = stw_lookup_context_locked( hglrcDst );
|
||||
|
|
@ -87,7 +93,7 @@ stw_copy_context(
|
|||
(void) mask;
|
||||
}
|
||||
|
||||
pipe_mutex_unlock( stw_dev->mutex );
|
||||
pipe_mutex_unlock( stw_dev->ctx_mutex );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -101,7 +107,7 @@ stw_share_lists(
|
|||
struct stw_context *ctx2;
|
||||
BOOL ret = FALSE;
|
||||
|
||||
pipe_mutex_lock( stw_dev->mutex );
|
||||
pipe_mutex_lock( stw_dev->ctx_mutex );
|
||||
|
||||
ctx1 = stw_lookup_context_locked( hglrc1 );
|
||||
ctx2 = stw_lookup_context_locked( hglrc2 );
|
||||
|
|
@ -111,7 +117,7 @@ stw_share_lists(
|
|||
ret = _mesa_share_state(ctx2->st->ctx, ctx1->st->ctx);
|
||||
}
|
||||
|
||||
pipe_mutex_unlock( stw_dev->mutex );
|
||||
pipe_mutex_unlock( stw_dev->ctx_mutex );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -124,8 +130,10 @@ stw_viewport(GLcontext * glctx, GLint x, GLint y,
|
|||
struct stw_framebuffer *fb;
|
||||
|
||||
fb = stw_framebuffer_from_hdc( ctx->hdc );
|
||||
if(fb)
|
||||
if(fb) {
|
||||
stw_framebuffer_update(fb);
|
||||
stw_framebuffer_release(fb);
|
||||
}
|
||||
}
|
||||
|
||||
UINT_PTR
|
||||
|
|
@ -189,9 +197,9 @@ stw_create_layer_context(
|
|||
ctx->st->ctx->DriverCtx = ctx;
|
||||
ctx->st->ctx->Driver.Viewport = stw_viewport;
|
||||
|
||||
pipe_mutex_lock( stw_dev->mutex );
|
||||
pipe_mutex_lock( stw_dev->ctx_mutex );
|
||||
ctx->hglrc = handle_table_add(stw_dev->ctx_table, ctx);
|
||||
pipe_mutex_unlock( stw_dev->mutex );
|
||||
pipe_mutex_unlock( stw_dev->ctx_mutex );
|
||||
if (!ctx->hglrc)
|
||||
goto no_hglrc;
|
||||
|
||||
|
|
@ -218,10 +226,10 @@ stw_delete_context(
|
|||
if (!stw_dev)
|
||||
return FALSE;
|
||||
|
||||
pipe_mutex_lock( stw_dev->mutex );
|
||||
pipe_mutex_lock( stw_dev->ctx_mutex );
|
||||
ctx = stw_lookup_context_locked(hglrc);
|
||||
handle_table_remove(stw_dev->ctx_table, hglrc);
|
||||
pipe_mutex_unlock( stw_dev->mutex );
|
||||
pipe_mutex_unlock( stw_dev->ctx_mutex );
|
||||
|
||||
if (ctx) {
|
||||
struct stw_context *curctx = stw_current_context();
|
||||
|
|
@ -248,9 +256,9 @@ stw_release_context(
|
|||
if (!stw_dev)
|
||||
return FALSE;
|
||||
|
||||
pipe_mutex_lock( stw_dev->mutex );
|
||||
pipe_mutex_lock( stw_dev->ctx_mutex );
|
||||
ctx = stw_lookup_context_locked( hglrc );
|
||||
pipe_mutex_unlock( stw_dev->mutex );
|
||||
pipe_mutex_unlock( stw_dev->ctx_mutex );
|
||||
|
||||
if (!ctx)
|
||||
return FALSE;
|
||||
|
|
@ -298,9 +306,9 @@ stw_make_current(
|
|||
HDC hdc,
|
||||
UINT_PTR hglrc )
|
||||
{
|
||||
struct stw_context *curctx;
|
||||
struct stw_context *ctx;
|
||||
struct stw_framebuffer *fb;
|
||||
struct stw_context *curctx = NULL;
|
||||
struct stw_context *ctx = NULL;
|
||||
struct stw_framebuffer *fb = NULL;
|
||||
|
||||
if (!stw_dev)
|
||||
goto fail;
|
||||
|
|
@ -322,13 +330,13 @@ stw_make_current(
|
|||
return st_make_current( NULL, NULL, NULL );
|
||||
}
|
||||
|
||||
pipe_mutex_lock( stw_dev->mutex );
|
||||
|
||||
pipe_mutex_lock( stw_dev->ctx_mutex );
|
||||
ctx = stw_lookup_context_locked( hglrc );
|
||||
pipe_mutex_unlock( stw_dev->ctx_mutex );
|
||||
if(!ctx)
|
||||
goto fail;
|
||||
|
||||
fb = stw_framebuffer_from_hdc_locked( hdc );
|
||||
fb = stw_framebuffer_from_hdc( hdc );
|
||||
if(!fb) {
|
||||
/* Applications should call SetPixelFormat before creating a context,
|
||||
* but not all do, and the opengl32 runtime seems to use a default pixel
|
||||
|
|
@ -336,13 +344,11 @@ stw_make_current(
|
|||
*/
|
||||
int iPixelFormat = GetPixelFormat(hdc);
|
||||
if(iPixelFormat)
|
||||
fb = stw_framebuffer_create_locked( hdc, iPixelFormat );
|
||||
fb = stw_framebuffer_create( hdc, iPixelFormat );
|
||||
if(!fb)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
pipe_mutex_unlock( stw_dev->mutex );
|
||||
|
||||
if(fb->iPixelFormat != ctx->iPixelFormat)
|
||||
goto fail;
|
||||
|
||||
|
|
@ -361,12 +367,16 @@ stw_make_current(
|
|||
|
||||
success:
|
||||
assert(fb);
|
||||
if(fb)
|
||||
if(fb) {
|
||||
stw_framebuffer_update(fb);
|
||||
stw_framebuffer_release(fb);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
||||
fail:
|
||||
if(fb)
|
||||
stw_framebuffer_release(fb);
|
||||
st_make_current( NULL, NULL, NULL );
|
||||
return FALSE;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -69,8 +69,6 @@ stw_flush_frontbuffer(struct pipe_screen *screen,
|
|||
fb = stw_framebuffer_from_hdc( hdc );
|
||||
/* fb can be NULL if window was destroyed already */
|
||||
if (fb) {
|
||||
pipe_mutex_lock( fb->mutex );
|
||||
|
||||
#if DEBUG
|
||||
{
|
||||
struct pipe_surface *surface2;
|
||||
|
|
@ -94,8 +92,7 @@ stw_flush_frontbuffer(struct pipe_screen *screen,
|
|||
|
||||
if(fb) {
|
||||
stw_framebuffer_update(fb);
|
||||
|
||||
pipe_mutex_unlock( fb->mutex );
|
||||
stw_framebuffer_release(fb);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -138,7 +135,8 @@ stw_init(const struct stw_winsys *stw_winsys)
|
|||
|
||||
stw_dev->screen->flush_frontbuffer = &stw_flush_frontbuffer;
|
||||
|
||||
pipe_mutex_init( stw_dev->mutex );
|
||||
pipe_mutex_init( stw_dev->ctx_mutex );
|
||||
pipe_mutex_init( stw_dev->fb_mutex );
|
||||
|
||||
stw_dev->ctx_table = handle_table_create();
|
||||
if (!stw_dev->ctx_table) {
|
||||
|
|
@ -179,7 +177,7 @@ stw_cleanup(void)
|
|||
if (!stw_dev)
|
||||
return;
|
||||
|
||||
pipe_mutex_lock( stw_dev->mutex );
|
||||
pipe_mutex_lock( stw_dev->ctx_mutex );
|
||||
{
|
||||
/* Ensure all contexts are destroyed */
|
||||
i = handle_table_get_first_handle(stw_dev->ctx_table);
|
||||
|
|
@ -189,11 +187,12 @@ stw_cleanup(void)
|
|||
}
|
||||
handle_table_destroy(stw_dev->ctx_table);
|
||||
}
|
||||
pipe_mutex_unlock( stw_dev->mutex );
|
||||
pipe_mutex_unlock( stw_dev->ctx_mutex );
|
||||
|
||||
stw_framebuffer_cleanup();
|
||||
|
||||
pipe_mutex_destroy( stw_dev->mutex );
|
||||
pipe_mutex_destroy( stw_dev->fb_mutex );
|
||||
pipe_mutex_destroy( stw_dev->ctx_mutex );
|
||||
|
||||
stw_dev->screen->destroy(stw_dev->screen);
|
||||
|
||||
|
|
|
|||
|
|
@ -57,10 +57,10 @@ struct stw_device
|
|||
unsigned pixelformat_count;
|
||||
unsigned pixelformat_extended_count;
|
||||
|
||||
pipe_mutex mutex;
|
||||
|
||||
pipe_mutex ctx_mutex;
|
||||
struct handle_table *ctx_table;
|
||||
|
||||
pipe_mutex fb_mutex;
|
||||
struct stw_framebuffer *fb_head;
|
||||
|
||||
#ifdef DEBUG
|
||||
|
|
|
|||
|
|
@ -45,6 +45,10 @@
|
|||
#include "stw_tls.h"
|
||||
|
||||
|
||||
/**
|
||||
* Search the framebuffer with the matching HWND while holding the
|
||||
* stw_dev::fb_mutex global lock.
|
||||
*/
|
||||
static INLINE struct stw_framebuffer *
|
||||
stw_framebuffer_from_hwnd_locked(
|
||||
HWND hwnd )
|
||||
|
|
@ -52,13 +56,20 @@ stw_framebuffer_from_hwnd_locked(
|
|||
struct stw_framebuffer *fb;
|
||||
|
||||
for (fb = stw_dev->fb_head; fb != NULL; fb = fb->next)
|
||||
if (fb->hWnd == hwnd)
|
||||
if (fb->hWnd == hwnd) {
|
||||
pipe_mutex_lock(fb->mutex);
|
||||
break;
|
||||
}
|
||||
|
||||
return fb;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Destroy this framebuffer. Both stw_dev::fb_mutex and stw_framebuffer::mutex
|
||||
* must be held, by this order. Obviously no further access to fb can be done
|
||||
* after this.
|
||||
*/
|
||||
static INLINE void
|
||||
stw_framebuffer_destroy_locked(
|
||||
struct stw_framebuffer *fb )
|
||||
|
|
@ -74,68 +85,24 @@ stw_framebuffer_destroy_locked(
|
|||
|
||||
st_unreference_framebuffer(fb->stfb);
|
||||
|
||||
pipe_mutex_unlock( fb->mutex );
|
||||
|
||||
pipe_mutex_destroy( fb->mutex );
|
||||
|
||||
FREE( fb );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @sa http://msdn.microsoft.com/en-us/library/ms644975(VS.85).aspx
|
||||
* @sa http://msdn.microsoft.com/en-us/library/ms644960(VS.85).aspx
|
||||
*/
|
||||
LRESULT CALLBACK
|
||||
stw_call_window_proc(
|
||||
int nCode,
|
||||
WPARAM wParam,
|
||||
LPARAM lParam )
|
||||
void
|
||||
stw_framebuffer_release(
|
||||
struct stw_framebuffer *fb)
|
||||
{
|
||||
struct stw_tls_data *tls_data;
|
||||
PCWPSTRUCT pParams = (PCWPSTRUCT)lParam;
|
||||
|
||||
tls_data = stw_tls_get_data();
|
||||
if(!tls_data)
|
||||
return 0;
|
||||
|
||||
if (nCode < 0)
|
||||
return CallNextHookEx(tls_data->hCallWndProcHook, nCode, wParam, lParam);
|
||||
|
||||
if (pParams->message == WM_SIZE && pParams->wParam != SIZE_MINIMIZED) {
|
||||
struct stw_framebuffer *fb;
|
||||
|
||||
pipe_mutex_lock( stw_dev->mutex );
|
||||
fb = stw_framebuffer_from_hwnd_locked( pParams->hwnd );
|
||||
pipe_mutex_unlock( stw_dev->mutex );
|
||||
|
||||
if(fb) {
|
||||
unsigned width = LOWORD( pParams->lParam );
|
||||
unsigned height = HIWORD( pParams->lParam );
|
||||
|
||||
pipe_mutex_lock( fb->mutex );
|
||||
fb->must_resize = TRUE;
|
||||
fb->width = width;
|
||||
fb->height = height;
|
||||
pipe_mutex_unlock( fb->mutex );
|
||||
}
|
||||
}
|
||||
|
||||
if (pParams->message == WM_DESTROY) {
|
||||
struct stw_framebuffer *fb;
|
||||
|
||||
pipe_mutex_lock( stw_dev->mutex );
|
||||
|
||||
fb = stw_framebuffer_from_hwnd_locked( pParams->hwnd );
|
||||
if(fb)
|
||||
stw_framebuffer_destroy_locked(fb);
|
||||
|
||||
pipe_mutex_unlock( stw_dev->mutex );
|
||||
}
|
||||
|
||||
return CallNextHookEx(tls_data->hCallWndProcHook, nCode, wParam, lParam);
|
||||
assert(fb);
|
||||
pipe_mutex_unlock( fb->mutex );
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
static INLINE void
|
||||
stw_framebuffer_get_size( struct stw_framebuffer *fb )
|
||||
{
|
||||
unsigned width, height;
|
||||
|
|
@ -161,10 +128,57 @@ stw_framebuffer_get_size( struct stw_framebuffer *fb )
|
|||
|
||||
|
||||
/**
|
||||
* Create a new framebuffer object which will correspond to the given HDC.
|
||||
* @sa http://msdn.microsoft.com/en-us/library/ms644975(VS.85).aspx
|
||||
* @sa http://msdn.microsoft.com/en-us/library/ms644960(VS.85).aspx
|
||||
*/
|
||||
LRESULT CALLBACK
|
||||
stw_call_window_proc(
|
||||
int nCode,
|
||||
WPARAM wParam,
|
||||
LPARAM lParam )
|
||||
{
|
||||
struct stw_tls_data *tls_data;
|
||||
PCWPSTRUCT pParams = (PCWPSTRUCT)lParam;
|
||||
struct stw_framebuffer *fb;
|
||||
|
||||
tls_data = stw_tls_get_data();
|
||||
if(!tls_data)
|
||||
return 0;
|
||||
|
||||
if (nCode < 0)
|
||||
return CallNextHookEx(tls_data->hCallWndProcHook, nCode, wParam, lParam);
|
||||
|
||||
if (pParams->message == WM_WINDOWPOSCHANGED) {
|
||||
/* We handle WM_WINDOWPOSCHANGED instead of WM_SIZE because according to
|
||||
* http://blogs.msdn.com/oldnewthing/archive/2008/01/15/7113860.aspx
|
||||
* WM_SIZE is generated from WM_WINDOWPOSCHANGED by DefWindowProc so it
|
||||
* can be masked out by the application. */
|
||||
LPWINDOWPOS lpWindowPos = (LPWINDOWPOS)pParams->lParam;
|
||||
if((lpWindowPos->flags & SWP_SHOWWINDOW) ||
|
||||
!(lpWindowPos->flags & SWP_NOSIZE)) {
|
||||
fb = stw_framebuffer_from_hwnd( pParams->hwnd );
|
||||
if(fb) {
|
||||
/* Size in WINDOWPOS includes the window frame, so get the size
|
||||
* of the client area via GetClientRect. */
|
||||
stw_framebuffer_get_size(fb);
|
||||
stw_framebuffer_release(fb);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (pParams->message == WM_DESTROY) {
|
||||
pipe_mutex_lock( stw_dev->fb_mutex );
|
||||
fb = stw_framebuffer_from_hwnd_locked( pParams->hwnd );
|
||||
if(fb)
|
||||
stw_framebuffer_destroy_locked(fb);
|
||||
pipe_mutex_unlock( stw_dev->fb_mutex );
|
||||
}
|
||||
|
||||
return CallNextHookEx(tls_data->hCallWndProcHook, nCode, wParam, lParam);
|
||||
}
|
||||
|
||||
|
||||
struct stw_framebuffer *
|
||||
stw_framebuffer_create_locked(
|
||||
stw_framebuffer_create(
|
||||
HDC hdc,
|
||||
int iPixelFormat )
|
||||
{
|
||||
|
|
@ -193,8 +207,16 @@ stw_framebuffer_create_locked(
|
|||
|
||||
pipe_mutex_init( fb->mutex );
|
||||
|
||||
/* This is the only case where we lock the stw_framebuffer::mutex before
|
||||
* stw_dev::fb_mutex, since no other thread can know about this framebuffer
|
||||
* and we must prevent any other thread from destroying it before we return.
|
||||
*/
|
||||
pipe_mutex_lock( fb->mutex );
|
||||
|
||||
pipe_mutex_lock( stw_dev->fb_mutex );
|
||||
fb->next = stw_dev->fb_head;
|
||||
stw_dev->fb_head = fb;
|
||||
pipe_mutex_unlock( stw_dev->fb_mutex );
|
||||
|
||||
return fb;
|
||||
}
|
||||
|
|
@ -204,8 +226,8 @@ BOOL
|
|||
stw_framebuffer_allocate(
|
||||
struct stw_framebuffer *fb)
|
||||
{
|
||||
pipe_mutex_lock( fb->mutex );
|
||||
|
||||
assert(fb);
|
||||
|
||||
if(!fb->stfb) {
|
||||
const struct stw_pixelformat_info *pfi = fb->pfi;
|
||||
enum pipe_format colorFormat, depthFormat, stencilFormat;
|
||||
|
|
@ -241,8 +263,6 @@ stw_framebuffer_allocate(
|
|||
fb->must_resize = TRUE;
|
||||
}
|
||||
|
||||
pipe_mutex_unlock( fb->mutex );
|
||||
|
||||
return fb->stfb ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
|
|
@ -279,24 +299,27 @@ stw_framebuffer_cleanup( void )
|
|||
struct stw_framebuffer *fb;
|
||||
struct stw_framebuffer *next;
|
||||
|
||||
pipe_mutex_lock( stw_dev->mutex );
|
||||
pipe_mutex_lock( stw_dev->fb_mutex );
|
||||
|
||||
fb = stw_dev->fb_head;
|
||||
while (fb) {
|
||||
next = fb->next;
|
||||
|
||||
pipe_mutex_lock(fb->mutex);
|
||||
stw_framebuffer_destroy_locked(fb);
|
||||
|
||||
fb = next;
|
||||
}
|
||||
stw_dev->fb_head = NULL;
|
||||
|
||||
pipe_mutex_unlock( stw_dev->mutex );
|
||||
pipe_mutex_unlock( stw_dev->fb_mutex );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Given an hdc, return the corresponding stw_framebuffer.
|
||||
*/
|
||||
struct stw_framebuffer *
|
||||
static INLINE struct stw_framebuffer *
|
||||
stw_framebuffer_from_hdc_locked(
|
||||
HDC hdc )
|
||||
{
|
||||
|
|
@ -313,8 +336,10 @@ stw_framebuffer_from_hdc_locked(
|
|||
return stw_framebuffer_from_hwnd_locked(hwnd);
|
||||
|
||||
for (fb = stw_dev->fb_head; fb != NULL; fb = fb->next)
|
||||
if (fb->hDC == hdc)
|
||||
if (fb->hDC == hdc) {
|
||||
pipe_mutex_lock(fb->mutex);
|
||||
break;
|
||||
}
|
||||
|
||||
return fb;
|
||||
}
|
||||
|
|
@ -329,9 +354,26 @@ stw_framebuffer_from_hdc(
|
|||
{
|
||||
struct stw_framebuffer *fb;
|
||||
|
||||
pipe_mutex_lock( stw_dev->mutex );
|
||||
pipe_mutex_lock( stw_dev->fb_mutex );
|
||||
fb = stw_framebuffer_from_hdc_locked(hdc);
|
||||
pipe_mutex_unlock( stw_dev->mutex );
|
||||
pipe_mutex_unlock( stw_dev->fb_mutex );
|
||||
|
||||
return fb;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Given an hdc, return the corresponding stw_framebuffer.
|
||||
*/
|
||||
struct stw_framebuffer *
|
||||
stw_framebuffer_from_hwnd(
|
||||
HWND hwnd )
|
||||
{
|
||||
struct stw_framebuffer *fb;
|
||||
|
||||
pipe_mutex_lock( stw_dev->fb_mutex );
|
||||
fb = stw_framebuffer_from_hwnd_locked(hwnd);
|
||||
pipe_mutex_unlock( stw_dev->fb_mutex );
|
||||
|
||||
return fb;
|
||||
}
|
||||
|
|
@ -351,22 +393,19 @@ stw_pixelformat_set(
|
|||
if (index >= count)
|
||||
return FALSE;
|
||||
|
||||
pipe_mutex_lock( stw_dev->mutex );
|
||||
|
||||
fb = stw_framebuffer_from_hdc_locked(hdc);
|
||||
if(fb) {
|
||||
/* SetPixelFormat must be called only once */
|
||||
pipe_mutex_unlock( stw_dev->mutex );
|
||||
stw_framebuffer_release( fb );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
fb = stw_framebuffer_create_locked(hdc, iPixelFormat);
|
||||
fb = stw_framebuffer_create(hdc, iPixelFormat);
|
||||
if(!fb) {
|
||||
pipe_mutex_unlock( stw_dev->mutex );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pipe_mutex_unlock( stw_dev->mutex );
|
||||
stw_framebuffer_release( fb );
|
||||
|
||||
/* Some applications mistakenly use the undocumented wglSetPixelFormat
|
||||
* function instead of SetPixelFormat, so we call SetPixelFormat here to
|
||||
|
|
@ -383,13 +422,16 @@ int
|
|||
stw_pixelformat_get(
|
||||
HDC hdc )
|
||||
{
|
||||
int iPixelFormat = 0;
|
||||
struct stw_framebuffer *fb;
|
||||
|
||||
fb = stw_framebuffer_from_hdc(hdc);
|
||||
if(!fb)
|
||||
return 0;
|
||||
if(fb) {
|
||||
iPixelFormat = fb->iPixelFormat;
|
||||
stw_framebuffer_release(fb);
|
||||
}
|
||||
|
||||
return fb->iPixelFormat;
|
||||
return iPixelFormat;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -405,10 +447,10 @@ stw_swap_buffers(
|
|||
if (fb == NULL)
|
||||
return FALSE;
|
||||
|
||||
if (!(fb->pfi->pfd.dwFlags & PFD_DOUBLEBUFFER))
|
||||
if (!(fb->pfi->pfd.dwFlags & PFD_DOUBLEBUFFER)) {
|
||||
stw_framebuffer_release(fb);
|
||||
return TRUE;
|
||||
|
||||
pipe_mutex_lock( fb->mutex );
|
||||
}
|
||||
|
||||
/* If we're swapping the buffer associated with the current context
|
||||
* we have to flush any pending rendering commands first.
|
||||
|
|
@ -419,7 +461,7 @@ stw_swap_buffers(
|
|||
|
||||
if(!st_get_framebuffer_surface( fb->stfb, ST_SURFACE_BACK_LEFT, &surface )) {
|
||||
/* FIXME: this shouldn't happen, but does on glean */
|
||||
pipe_mutex_unlock( fb->mutex );
|
||||
stw_framebuffer_release(fb);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
@ -433,8 +475,7 @@ stw_swap_buffers(
|
|||
stw_dev->stw_winsys->flush_frontbuffer( screen, surface, hdc );
|
||||
|
||||
stw_framebuffer_update(fb);
|
||||
|
||||
pipe_mutex_unlock( fb->mutex );
|
||||
stw_framebuffer_release(fb);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,6 +41,23 @@ struct stw_pixelformat_info;
|
|||
*/
|
||||
struct stw_framebuffer
|
||||
{
|
||||
/**
|
||||
* This mutex has two purposes:
|
||||
* - protect the access to the mutable data members below
|
||||
* - prevent the the framebuffer from being deleted while being accessed.
|
||||
*
|
||||
* It is OK to lock this mutex while holding the stw_device::fb_mutex lock,
|
||||
* but the opposite must never happen.
|
||||
*/
|
||||
pipe_mutex mutex;
|
||||
|
||||
/*
|
||||
* Immutable members.
|
||||
*
|
||||
* Note that even access to immutable members implies acquiring the mutex
|
||||
* above, to prevent the framebuffer from being destroyed.
|
||||
*/
|
||||
|
||||
HDC hDC;
|
||||
HWND hWnd;
|
||||
|
||||
|
|
@ -48,7 +65,10 @@ struct stw_framebuffer
|
|||
const struct stw_pixelformat_info *pfi;
|
||||
GLvisual visual;
|
||||
|
||||
pipe_mutex mutex;
|
||||
/*
|
||||
* Mutable members.
|
||||
*/
|
||||
|
||||
struct st_framebuffer *stfb;
|
||||
|
||||
/* FIXME: Make this work for multiple contexts bound to the same framebuffer */
|
||||
|
|
@ -56,15 +76,52 @@ struct stw_framebuffer
|
|||
unsigned width;
|
||||
unsigned height;
|
||||
|
||||
/** This is protected by stw_device::mutex, not the mutex above */
|
||||
/**
|
||||
* This is protected by stw_device::fb_mutex, not the mutex above.
|
||||
*
|
||||
* Deletions must be done by first acquiring stw_device::fb_mutex, and then
|
||||
* acquiring the stw_framebuffer::mutex of the framebuffer to be deleted.
|
||||
* This ensures that nobody else is reading/writing to the.
|
||||
*
|
||||
* It is not necessary to aquire the mutex above to navigate the linked list
|
||||
* given that deletions are done with stw_device::fb_mutex held, so no other
|
||||
* thread can delete.
|
||||
*/
|
||||
struct stw_framebuffer *next;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Create a new framebuffer object which will correspond to the given HDC.
|
||||
*
|
||||
* This function will acquire stw_framebuffer::mutex. stw_framebuffer_release
|
||||
* must be called when done
|
||||
*/
|
||||
struct stw_framebuffer *
|
||||
stw_framebuffer_create_locked(
|
||||
stw_framebuffer_create(
|
||||
HDC hdc,
|
||||
int iPixelFormat );
|
||||
|
||||
/**
|
||||
* Search a framebuffer with a matching HWND.
|
||||
*
|
||||
* This function will acquire stw_framebuffer::mutex. stw_framebuffer_release
|
||||
* must be called when done
|
||||
*/
|
||||
struct stw_framebuffer *
|
||||
stw_framebuffer_from_hwnd(
|
||||
HWND hwnd );
|
||||
|
||||
/**
|
||||
* Search a framebuffer with a matching HDC.
|
||||
*
|
||||
* This function will acquire stw_framebuffer::mutex. stw_framebuffer_release
|
||||
* must be called when done
|
||||
*/
|
||||
struct stw_framebuffer *
|
||||
stw_framebuffer_from_hdc(
|
||||
HDC hdc );
|
||||
|
||||
BOOL
|
||||
stw_framebuffer_allocate(
|
||||
struct stw_framebuffer *fb );
|
||||
|
|
@ -73,15 +130,19 @@ void
|
|||
stw_framebuffer_update(
|
||||
struct stw_framebuffer *fb);
|
||||
|
||||
/**
|
||||
* Release stw_framebuffer::mutex lock. This framebuffer must not be accessed
|
||||
* after calling this function, as it may have been deleted by another thread
|
||||
* in the meanwhile.
|
||||
*/
|
||||
void
|
||||
stw_framebuffer_release(
|
||||
struct stw_framebuffer *fb);
|
||||
|
||||
/**
|
||||
* Cleanup any existing framebuffers when exiting application.
|
||||
*/
|
||||
void
|
||||
stw_framebuffer_cleanup(void);
|
||||
|
||||
struct stw_framebuffer *
|
||||
stw_framebuffer_from_hdc_locked(
|
||||
HDC hdc );
|
||||
|
||||
struct stw_framebuffer *
|
||||
stw_framebuffer_from_hdc(
|
||||
HDC hdc );
|
||||
|
||||
#endif /* STW_FRAMEBUFFER_H */
|
||||
|
|
|
|||
|
|
@ -305,6 +305,7 @@ CallCreateNewScreen(Display *dpy, int scrn, __GLXscreenConfigs *psc,
|
|||
drm_handle_t hFB;
|
||||
int junk;
|
||||
const __DRIconfig **driver_configs;
|
||||
__GLcontextModes *visual;
|
||||
|
||||
/* DRI protocol version. */
|
||||
dri_version.major = driDpy->driMajor;
|
||||
|
|
@ -417,6 +418,28 @@ CallCreateNewScreen(Display *dpy, int scrn, __GLXscreenConfigs *psc,
|
|||
psc->configs = driConvertConfigs(psc->core, psc->configs, driver_configs);
|
||||
psc->visuals = driConvertConfigs(psc->core, psc->visuals, driver_configs);
|
||||
|
||||
/* Visuals with depth != screen depth are subject to automatic compositing
|
||||
* in the X server, so DRI1 can't render to them properly. Mark them as
|
||||
* non-conformant to prevent apps from picking them up accidentally.
|
||||
*/
|
||||
for (visual = psc->visuals; visual; visual = visual->next) {
|
||||
XVisualInfo template;
|
||||
XVisualInfo *visuals;
|
||||
int num_visuals;
|
||||
long mask;
|
||||
|
||||
template.visualid = visual->visualID;
|
||||
mask = VisualIDMask;
|
||||
visuals = XGetVisualInfo(dpy, mask, &template, &num_visuals);
|
||||
|
||||
if (visuals) {
|
||||
if (num_visuals > 0 && visuals->depth != DefaultDepth(dpy, scrn))
|
||||
visual->visualRating = GLX_NON_CONFORMANT_CONFIG;
|
||||
|
||||
XFree(visuals);
|
||||
}
|
||||
}
|
||||
|
||||
return psp;
|
||||
|
||||
handle_error:
|
||||
|
|
|
|||
|
|
@ -137,22 +137,15 @@ find_translated_vp(struct st_context *st,
|
|||
|
||||
for (inAttr = 0; inAttr < FRAG_ATTRIB_MAX; inAttr++) {
|
||||
if (fragInputsRead & (1 << inAttr)) {
|
||||
stfp->input_to_slot[inAttr] = numIn;
|
||||
numIn++;
|
||||
if ((fragInputsRead & FRAG_BIT_FOGC)) {
|
||||
if (stfp->Base.UsesPointCoord) {
|
||||
stfp->input_to_slot[inAttr] = numIn;
|
||||
numIn++;
|
||||
/* leave placeholders for the
|
||||
* extra registers we extract from fog */
|
||||
if (stfp->Base.UsesFrontFacing ||
|
||||
stfp->Base.UsesPointCoord) {
|
||||
numIn += 2;
|
||||
}
|
||||
if (stfp->Base.UsesFrontFacing) {
|
||||
stfp->input_to_slot[inAttr] = numIn;
|
||||
numIn++;
|
||||
}
|
||||
if (stfp->Base.UsesFogFragCoord) {
|
||||
stfp->input_to_slot[inAttr] = numIn;
|
||||
numIn++;
|
||||
}
|
||||
} else {
|
||||
stfp->input_to_slot[inAttr] = numIn;
|
||||
numIn++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
|
|||
|
|
@ -1037,10 +1037,16 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy,
|
|||
st_cond_flush_get_tex_transfer(st, rbRead->texture, 0, 0, 0,
|
||||
PIPE_TRANSFER_READ, srcx, srcy, width,
|
||||
height);
|
||||
struct pipe_transfer *ptTex;
|
||||
enum pipe_transfer_usage transfer_usage;
|
||||
|
||||
struct pipe_transfer *ptTex =
|
||||
st_cond_flush_get_tex_transfer(st, pt, 0, 0, 0, PIPE_TRANSFER_WRITE,
|
||||
0, 0, width, height);
|
||||
if (type == GL_DEPTH && pf_is_depth_and_stencil(pt->format))
|
||||
transfer_usage = PIPE_TRANSFER_READ_WRITE;
|
||||
else
|
||||
transfer_usage = PIPE_TRANSFER_WRITE;
|
||||
|
||||
ptTex = st_cond_flush_get_tex_transfer(st, pt, 0, 0, 0, transfer_usage,
|
||||
0, 0, width, height);
|
||||
|
||||
if (type == GL_COLOR) {
|
||||
/* alternate path using get/put_tile() */
|
||||
|
|
|
|||
|
|
@ -529,6 +529,7 @@ st_TexImage(GLcontext * ctx,
|
|||
GLint texelBytes, sizeInBytes;
|
||||
GLuint dstRowStride;
|
||||
struct gl_pixelstore_attrib unpackNB;
|
||||
enum pipe_transfer_usage transfer_usage;
|
||||
|
||||
DBG("%s target %s level %d %dx%dx%d border %d\n", __FUNCTION__,
|
||||
_mesa_lookup_enum_by_nr(target), level, width, height, depth, border);
|
||||
|
|
@ -680,8 +681,14 @@ st_TexImage(GLcontext * ctx,
|
|||
}
|
||||
|
||||
if (stImage->pt) {
|
||||
if (format == GL_DEPTH_COMPONENT &&
|
||||
pf_is_depth_and_stencil(stImage->pt->format))
|
||||
transfer_usage = PIPE_TRANSFER_READ_WRITE;
|
||||
else
|
||||
transfer_usage = PIPE_TRANSFER_WRITE;
|
||||
|
||||
texImage->Data = st_texture_image_map(ctx->st, stImage, 0,
|
||||
PIPE_TRANSFER_WRITE, 0, 0,
|
||||
transfer_usage, 0, 0,
|
||||
stImage->base.Width,
|
||||
stImage->base.Height);
|
||||
if(stImage->transfer)
|
||||
|
|
@ -742,7 +749,7 @@ st_TexImage(GLcontext * ctx,
|
|||
st_texture_image_unmap(ctx->st, stImage);
|
||||
/* map next slice of 3D texture */
|
||||
texImage->Data = st_texture_image_map(ctx->st, stImage, i + 1,
|
||||
PIPE_TRANSFER_WRITE, 0, 0,
|
||||
transfer_usage, 0, 0,
|
||||
stImage->base.Width,
|
||||
stImage->base.Height);
|
||||
src += srcImageStride;
|
||||
|
|
@ -1041,6 +1048,7 @@ st_TexSubimage(GLcontext *ctx, GLint dims, GLenum target, GLint level,
|
|||
_mesa_image_image_stride(packing, width, height, format, type);
|
||||
GLint i;
|
||||
const GLubyte *src;
|
||||
enum pipe_transfer_usage transfer_usage;
|
||||
|
||||
DBG("%s target %s level %d offset %d,%d %dx%d\n", __FUNCTION__,
|
||||
_mesa_lookup_enum_by_nr(target),
|
||||
|
|
@ -1072,10 +1080,16 @@ st_TexSubimage(GLcontext *ctx, GLint dims, GLenum target, GLint level,
|
|||
* from uploading the buffer under us.
|
||||
*/
|
||||
if (stImage->pt) {
|
||||
if (format == GL_DEPTH_COMPONENT &&
|
||||
pf_is_depth_and_stencil(stImage->pt->format))
|
||||
transfer_usage = PIPE_TRANSFER_READ_WRITE;
|
||||
else
|
||||
transfer_usage = PIPE_TRANSFER_WRITE;
|
||||
|
||||
st_teximage_flush_before_map(ctx->st, stImage->pt, 0, level,
|
||||
PIPE_TRANSFER_WRITE);
|
||||
transfer_usage);
|
||||
texImage->Data = st_texture_image_map(ctx->st, stImage, zoffset,
|
||||
PIPE_TRANSFER_WRITE,
|
||||
transfer_usage,
|
||||
xoffset, yoffset,
|
||||
width, height);
|
||||
}
|
||||
|
|
@ -1106,7 +1120,7 @@ st_TexSubimage(GLcontext *ctx, GLint dims, GLenum target, GLint level,
|
|||
/* map next slice of 3D texture */
|
||||
texImage->Data = st_texture_image_map(ctx->st, stImage,
|
||||
zoffset + i + 1,
|
||||
PIPE_TRANSFER_WRITE,
|
||||
transfer_usage,
|
||||
xoffset, yoffset,
|
||||
width, height);
|
||||
src += srcImageStride;
|
||||
|
|
@ -1274,6 +1288,7 @@ fallback_copy_texsubimage(GLcontext *ctx, GLenum target, GLint level,
|
|||
struct pipe_screen *screen = pipe->screen;
|
||||
struct pipe_transfer *src_trans;
|
||||
GLvoid *texDest;
|
||||
enum pipe_transfer_usage transfer_usage;
|
||||
|
||||
assert(width <= MAX_WIDTH);
|
||||
|
||||
|
|
@ -1288,10 +1303,16 @@ fallback_copy_texsubimage(GLcontext *ctx, GLenum target, GLint level,
|
|||
srcX, srcY,
|
||||
width, height);
|
||||
|
||||
st_teximage_flush_before_map(ctx->st, stImage->pt, 0, 0,
|
||||
PIPE_TRANSFER_WRITE);
|
||||
if (baseFormat == GL_DEPTH_COMPONENT &&
|
||||
pf_is_depth_and_stencil(stImage->pt->format))
|
||||
transfer_usage = PIPE_TRANSFER_READ_WRITE;
|
||||
else
|
||||
transfer_usage = PIPE_TRANSFER_WRITE;
|
||||
|
||||
texDest = st_texture_image_map(ctx->st, stImage, 0, PIPE_TRANSFER_WRITE,
|
||||
st_teximage_flush_before_map(ctx->st, stImage->pt, 0, 0,
|
||||
transfer_usage);
|
||||
|
||||
texDest = st_texture_image_map(ctx->st, stImage, 0, transfer_usage,
|
||||
destX, destY, width, height);
|
||||
|
||||
if (baseFormat == GL_DEPTH_COMPONENT ||
|
||||
|
|
|
|||
|
|
@ -280,7 +280,8 @@ st_notify_swapbuffers(struct st_framebuffer *stfb)
|
|||
PIPE_FLUSH_SWAPBUFFERS |
|
||||
PIPE_FLUSH_FRAME,
|
||||
NULL );
|
||||
ctx->st->frontbuffer_status = FRONT_STATUS_COPY_OF_BACK;
|
||||
if (st_renderbuffer(stfb->Base.Attachment[BUFFER_BACK_LEFT].Renderbuffer))
|
||||
ctx->st->frontbuffer_status = FRONT_STATUS_COPY_OF_BACK;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -122,8 +122,15 @@ map_register_file_index(
|
|||
SWIZZLE_X,
|
||||
SWIZZLE_X,
|
||||
SWIZZLE_X);
|
||||
/* register after fog */
|
||||
return inputMapping[index] + 1;
|
||||
} else {
|
||||
/* fixme: point coord */
|
||||
*swizzle = MAKE_SWIZZLE4(SWIZZLE_Z,
|
||||
SWIZZLE_W,
|
||||
SWIZZLE_Z,
|
||||
SWIZZLE_W);
|
||||
/* register after frontface */
|
||||
return inputMapping[index] + 2;
|
||||
}
|
||||
}
|
||||
/* inputs are mapped according to the user-defined map */
|
||||
|
|
|
|||
|
|
@ -453,20 +453,34 @@ st_translate_fragment_program(struct st_context *st,
|
|||
stfp->input_semantic_index[slot] = 1;
|
||||
interpMode[slot] = TGSI_INTERPOLATE_LINEAR;
|
||||
break;
|
||||
case FRAG_ATTRIB_FOGC:
|
||||
if (stfp->Base.UsesPointCoord) {
|
||||
stfp->input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
|
||||
stfp->input_semantic_index[slot] = num_generic++;
|
||||
interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE;
|
||||
} else if (stfp->Base.UsesFrontFacing) {
|
||||
stfp->input_semantic_name[slot] = TGSI_SEMANTIC_FACE;
|
||||
stfp->input_semantic_index[slot] = 0;
|
||||
interpMode[slot] = TGSI_INTERPOLATE_CONSTANT;
|
||||
} else {
|
||||
case FRAG_ATTRIB_FOGC: {
|
||||
int extra_decls = 0;
|
||||
if (stfp->Base.UsesFogFragCoord) {
|
||||
stfp->input_semantic_name[slot] = TGSI_SEMANTIC_FOG;
|
||||
stfp->input_semantic_index[slot] = 0;
|
||||
interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE;
|
||||
input_flags[slot] = stfp->Base.Base.InputFlags[attr];
|
||||
++extra_decls;
|
||||
}
|
||||
if (stfp->Base.UsesFrontFacing) {
|
||||
GLint idx = slot + extra_decls;
|
||||
stfp->input_semantic_name[idx] = TGSI_SEMANTIC_FACE;
|
||||
stfp->input_semantic_index[idx] = 0;
|
||||
interpMode[idx] = TGSI_INTERPOLATE_CONSTANT;
|
||||
input_flags[idx] = stfp->Base.Base.InputFlags[attr];
|
||||
++extra_decls;
|
||||
}
|
||||
if (stfp->Base.UsesPointCoord) {
|
||||
GLint idx = slot + extra_decls;
|
||||
stfp->input_semantic_name[idx] = TGSI_SEMANTIC_GENERIC;
|
||||
stfp->input_semantic_index[idx] = num_generic++;
|
||||
interpMode[idx] = TGSI_INTERPOLATE_PERSPECTIVE;
|
||||
input_flags[idx] = stfp->Base.Base.InputFlags[attr];
|
||||
++extra_decls;
|
||||
}
|
||||
fs_num_inputs += extra_decls - 1;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case FRAG_ATTRIB_TEX0:
|
||||
case FRAG_ATTRIB_TEX1:
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue