diff options
Diffstat (limited to 'mesalib')
51 files changed, 1031 insertions, 428 deletions
diff --git a/mesalib/Android.common.mk b/mesalib/Android.common.mk index 18e5726fa..d0a5f1aa4 100644 --- a/mesalib/Android.common.mk +++ b/mesalib/Android.common.mk @@ -34,10 +34,8 @@ LOCAL_C_INCLUDES += \ $(MESA_TOP)/include # define ANDROID_VERSION (e.g., 4.0.x => 0x0400) -major := $(word 1, $(subst ., , $(PLATFORM_VERSION))) -minor := $(word 2, $(subst ., , $(PLATFORM_VERSION))) LOCAL_CFLAGS += \ - -DANDROID_VERSION=0x0$(major)0$(minor) + -DANDROID_VERSION=0x0$(MESA_ANDROID_MAJOR_VERSION)0$(MESA_ANDROID_MINOR_VERSION) LOCAL_CFLAGS += \ -DHAVE_PTHREAD=1 \ diff --git a/mesalib/Android.mk b/mesalib/Android.mk index 6a3014c81..80c0e1395 100644 --- a/mesalib/Android.mk +++ b/mesalib/Android.mk @@ -30,6 +30,11 @@ # module will also be built. DRI modules will be loaded by libGLES_mesa. MESA_TOP := $(call my-dir) + +MESA_ANDROID_MAJOR_VERSION := $(word 1, $(subst ., , $(PLATFORM_VERSION))) +MESA_ANDROID_MINOR_VERSION := $(word 2, $(subst ., , $(PLATFORM_VERSION))) +MESA_ANDROID_VERSION := $(MESA_ANDROID_MAJOR_VERSION).$(MESA_ANDROID_MINOR_VERSION) + MESA_COMMON_MK := $(MESA_TOP)/Android.common.mk MESA_PYTHON2 := python diff --git a/mesalib/bin/.gitignore b/mesalib/bin/.gitignore index dfaa6d366..aa4577e91 100644 --- a/mesalib/bin/.gitignore +++ b/mesalib/bin/.gitignore @@ -6,3 +6,4 @@ install-sh ylwrap compile ar-lib +/test-driver diff --git a/mesalib/configure.ac b/mesalib/configure.ac index 1294740a4..1414ce826 100644 --- a/mesalib/configure.ac +++ b/mesalib/configure.ac @@ -73,7 +73,7 @@ AC_PATH_PROG([PERL], [perl]) AC_CHECK_PROG(INDENT, indent, indent, cat) if test "x$INDENT" != "xcat"; then - AC_SUBST(INDENT_FLAGS, '-i4 -nut -br -brs -npcs -ce -T GLubyte -T GLbyte -T Bool') + AC_SUBST(INDENT_FLAGS, '-i4 -nut -br -brs -npcs -ce -TGLubyte -TGLbyte -TBool') fi dnl Our fallback install-sh is a symlink to minstall. Use the existing @@ -1677,7 +1677,8 @@ if test "x$enable_gallium_llvm" = xyes; then if test "x$LLVM_CONFIG" != xno; then LLVM_VERSION=`$LLVM_CONFIG --version | sed 's/svn.*//g'` - if test "x$with_llvm_shared_libs" = xyes; then + LLVM_VERSION_INT=`echo $LLVM_VERSION | sed -e 's/\([[0-9]]\)\.\([[0-9]]\)/\10\2/g'` + if test "x$with_llvm_shared_libs" = xyes; then dnl We can't use $LLVM_VERSION because it has 'svn' stripped out, LLVM_LIBS="-lLLVM-`$LLVM_CONFIG --version`" else @@ -1800,24 +1801,19 @@ gallium_require_drm_loader() { radeon_llvm_check() { LLVM_REQUIRED_VERSION_MAJOR="3" LLVM_REQUIRED_VERSION_MINOR="2" - LLVM_AVAILABLE_VERSION_MAJOR=`echo $LLVM_VERSION | cut -d. -f1` - LLVM_AVAILABLE_VERSION_MINOR=`echo $LLVM_VERSION | cut -d. -f2` - if test "$LLVM_AVAILABLE_VERSION_MAJOR" -lt "$LLVM_REQUIRED_VERSION_MAJOR" -o [ "$LLVM_AVAILABLE_VERSION_MAJOR" -eq "$LLVM_REQUIRED_VERSION_MAJOR" -a "$LLVM_AVAILABLE_VERSION_MINOR" -lt "$LLVM_REQUIRED_VERSION_MINOR" ] ; then - AC_MSG_ERROR([LLVM $LLVM_REQUIRED_VERSION_MAJOR.$LLVM_REQUIRED_VERSION_MINOR or newer with AMDGPU target enabled is required. + if test "$LLVM_VERSION_INT" -lt "${LLVM_REQUIRED_VERSION_MAJOR}0${LLVM_REQUIRED_VERSION_MINOR}"; then + AC_MSG_ERROR([LLVM $LLVM_REQUIRED_VERSION_MAJOR.$LLVM_REQUIRED_VERSION_MINOR or newer with R600 target enabled is required. To use the r600/radeonsi LLVM backend, you need to fetch the LLVM source from: git://people.freedesktop.org/~tstellar/llvm master - and build with --enable-experimental-targets=AMDGPU]) + and build with --enable-experimental-targets=R600]) fi - if test true && $LLVM_CONFIG --targets-built | grep -qv '\<AMDGPU\>' ; then - AC_MSG_ERROR([LLVM AMDGPU Target not enabled. - To use the r600/radeonsi LLVM backend, you need to fetch the LLVM source from: - git://people.freedesktop.org/~tstellar/llvm master - and build with --enable-experimental-targets=AMDGPU]) + if test true && $LLVM_CONFIG --targets-built | grep -qv '\<R600\>' ; then + AC_MSG_ERROR([LLVM R600 Target not enabled. You can enable it when building the LLVM + sources with the --enable-experimental-targets=R600 + configure flag]) fi AC_MSG_WARN([Please ensure you use the latest llvm tree from git://people.freedesktop.org/~tstellar/llvm master before submitting a bug]) - if test "x$LLVM_VERSION" = "x3.2"; then - LLVM_LIBS="$LLVM_LIBS `$LLVM_CONFIG --libs amdgpu`" - fi + LLVM_LIBS="$LLVM_LIBS `$LLVM_CONFIG --libs r600`" } dnl Gallium drivers diff --git a/mesalib/include/EGL/eglext.h b/mesalib/include/EGL/eglext.h index a5c9009e1..b2b5a8038 100644 --- a/mesalib/include/EGL/eglext.h +++ b/mesalib/include/EGL/eglext.h @@ -34,7 +34,7 @@ extern "C" { /* Header file version number */ /* Current version at http://www.khronos.org/registry/egl/ */ -/* $Revision: 19571 $ on $Date: 2012-10-31 10:10:33 -0700 (Wed, 31 Oct 2012) $ */ +/* $Revision: 19987 $ on $Date: 2012-12-13 16:46:46 -0800 (Thu, 13 Dec 2012) $ */ #define EGL_EGLEXT_VERSION 14 #ifndef EGL_KHR_config_attribs @@ -250,7 +250,6 @@ struct EGLClientPixmapHI EGLint iHeight; EGLint iStride; }; - #ifdef EGL_EGLEXT_PROTOTYPES EGLAPI EGLSurface EGLAPIENTRY eglCreatePixmapSurfaceHI(EGLDisplay dpy, EGLConfig config, struct EGLClientPixmapHI* pixmap); #endif /* EGL_EGLEXT_PROTOTYPES */ @@ -316,9 +315,7 @@ typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSURFACEPOINTERANGLEPROC) (EGLDisplay #if KHRONOS_SUPPORT_INT64 /* EGLuint64NV requires 64-bit uint support */ #ifndef EGL_NV_system_time #define EGL_NV_system_time 1 - typedef khronos_utime_nanoseconds_t EGLuint64NV; - #ifdef EGL_EGLEXT_PROTOTYPES EGLAPI EGLuint64NV EGLAPIENTRY eglGetSystemTimeFrequencyNV(void); EGLAPI EGLuint64NV EGLAPIENTRY eglGetSystemTimeNV(void); @@ -470,10 +467,75 @@ EGLAPI EGLint EGLAPIENTRY eglWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint typedef EGLint (EGLAPIENTRYP PFNEGLWAITSYNCKHRPROC)(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags); #endif +#ifndef EGL_NV_post_convert_rounding +#define EGL_NV_post_convert_rounding 1 +/* No tokens or entry points, just relaxes behavior of SwapBuffers */ +#endif + +#ifndef EGL_NV_native_query +#define EGL_NV_native_query 1 +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglQueryNativeDisplayNV( EGLDisplay dpy, EGLNativeDisplayType* display_id); +EGLAPI EGLBoolean EGLAPIENTRY eglQueryNativeWindowNV( EGLDisplay dpy, EGLSurface surf, EGLNativeWindowType* window); +EGLAPI EGLBoolean EGLAPIENTRY eglQueryNativePixmapNV( EGLDisplay dpy, EGLSurface surf, EGLNativePixmapType* pixmap); +#endif /* EGL_EGLEXT_PROTOTYPES */ +typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYNATIVEDISPLAYNVPROC)(EGLDisplay dpy, EGLNativeDisplayType *display_id); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYNATIVEWINDOWNVPROC)(EGLDisplay dpy, EGLSurface surf, EGLNativeWindowType *window); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYNATIVEPIXMAPNVPROC)(EGLDisplay dpy, EGLSurface surf, EGLNativePixmapType *pixmap); +#endif + +#ifndef EGL_NV_3dvision_surface +#define EGL_NV_3dvision_surface 1 +#define EGL_AUTO_STEREO_NV 0x3136 +#endif + +#ifndef EGL_ANDROID_framebuffer_target +#define EGL_ANDROID_framebuffer_target 1 +#define EGL_FRAMEBUFFER_TARGET_ANDROID 0x3147 +#endif + +#ifndef EGL_ANDROID_blob_cache +#define EGL_ANDROID_blob_cache 1 +typedef khronos_ssize_t EGLsizeiANDROID; +typedef void (*EGLSetBlobFuncANDROID) (const void *key, EGLsizeiANDROID keySize, const void *value, EGLsizeiANDROID valueSize); +typedef EGLsizeiANDROID (*EGLGetBlobFuncANDROID) (const void *key, EGLsizeiANDROID keySize, void *value, EGLsizeiANDROID valueSize); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI void EGLAPIENTRY eglSetBlobCacheFuncsANDROID(EGLDisplay dpy, EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get); +#endif /* EGL_EGLEXT_PROTOTYPES */ +typedef void (EGLAPIENTRYP PFNEGLSETBLOBCACHEFUNCSANDROIDPROC)(EGLDisplay dpy, EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get); +#endif + +#ifndef EGL_ANDROID_image_native_buffer +#define EGL_ANDROID_image_native_buffer 1 +#define EGL_NATIVE_BUFFER_ANDROID 0x3140 +#endif + +#ifndef EGL_ANDROID_native_fence_sync +#define EGL_ANDROID_native_fence_sync 1 +#define EGL_SYNC_NATIVE_FENCE_ANDROID 0x3144 +#define EGL_SYNC_NATIVE_FENCE_FD_ANDROID 0x3145 +#define EGL_SYNC_NATIVE_FENCE_SIGNALED_ANDROID 0x3146 +#define EGL_NO_NATIVE_FENCE_FD_ANDROID -1 +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLint EGLAPIENTRY eglDupNativeFenceFDANDROID( EGLDisplay dpy, EGLSyncKHR); +#endif /* EGL_EGLEXT_PROTOTYPES */ +typedef EGLint (EGLAPIENTRYP PFNEGLDUPNATIVEFENCEFDANDROIDPROC)(EGLDisplay dpy, EGLSyncKHR); +#endif + +#ifndef EGL_ANDROID_recordable +#define EGL_ANDROID_recordable 1 +#define EGL_RECORDABLE_ANDROID 0x3142 +#endif + +#ifndef EGL_EXT_buffer_age +#define EGL_EXT_buffer_age 1 +#define EGL_BUFFER_AGE_EXT 0x313D +#endif + #include <EGL/eglmesaext.h> #ifdef __cplusplus } #endif -#endif +#endif /* __eglext_h_ */ diff --git a/mesalib/src/.gitignore b/mesalib/src/.gitignore index 5fc607b9e..ddfb40586 100644 --- a/mesalib/src/.gitignore +++ b/mesalib/src/.gitignore @@ -1 +1,3 @@ /Makefile +*.trs +*.log diff --git a/mesalib/src/gallium/auxiliary/util/u_blitter.c b/mesalib/src/gallium/auxiliary/util/u_blitter.c index 7c7e06219..95224020c 100644 --- a/mesalib/src/gallium/auxiliary/util/u_blitter.c +++ b/mesalib/src/gallium/auxiliary/util/u_blitter.c @@ -127,6 +127,10 @@ struct blitter_context_priv void (*delete_fs_state)(struct pipe_context *, void *); }; +static struct pipe_surface * +util_blitter_get_next_surface_layer(struct pipe_context *pipe, + struct pipe_surface *surf); + struct blitter_context *util_blitter_create(struct pipe_context *pipe) { struct blitter_context_priv *ctx; @@ -143,6 +147,7 @@ struct blitter_context *util_blitter_create(struct pipe_context *pipe) ctx->base.pipe = pipe; ctx->base.draw_rectangle = util_blitter_draw_rectangle; + ctx->base.get_next_surface_layer = util_blitter_get_next_surface_layer; ctx->bind_fs_state = pipe->bind_fs_state; ctx->delete_fs_state = pipe->delete_fs_state; @@ -681,6 +686,11 @@ static void blitter_set_texcoords(struct blitter_context_priv *ctx, } break; + case PIPE_TEXTURE_CUBE_ARRAY: + for (i = 0; i < 4; i++) + ctx->vertices[i][1][3] = (float) (layer / 6); /*w*/ + break; + case PIPE_TEXTURE_2D: for (i = 0; i < 4; i++) { ctx->vertices[i][1][2] = (float) sample; /*r*/ @@ -1056,14 +1066,28 @@ void util_blitter_custom_clear_depth(struct blitter_context *blitter, void util_blitter_default_dst_texture(struct pipe_surface *dst_templ, struct pipe_resource *dst, unsigned dstlevel, - unsigned dstz, - const struct pipe_box *srcbox) + unsigned dstz) { memset(dst_templ, 0, sizeof(*dst_templ)); dst_templ->format = util_format_linear(dst->format); dst_templ->u.tex.level = dstlevel; dst_templ->u.tex.first_layer = dstz; - dst_templ->u.tex.last_layer = dstz + srcbox->depth - 1; + dst_templ->u.tex.last_layer = dstz; +} + +static struct pipe_surface * +util_blitter_get_next_surface_layer(struct pipe_context *pipe, + struct pipe_surface *surf) +{ + struct pipe_surface dst_templ; + + memset(&dst_templ, 0, sizeof(dst_templ)); + dst_templ.format = surf->format; + dst_templ.u.tex.level = surf->u.tex.level; + dst_templ.u.tex.first_layer = surf->u.tex.first_layer + 1; + dst_templ.u.tex.last_layer = surf->u.tex.last_layer + 1; + + return pipe->create_surface(pipe, surf->texture, &dst_templ); } void util_blitter_default_src_texture(struct pipe_sampler_view *src_templ, @@ -1176,12 +1200,16 @@ void util_blitter_copy_texture(struct blitter_context *blitter, struct pipe_context *pipe = ctx->base.pipe; struct pipe_surface *dst_view, dst_templ; struct pipe_sampler_view src_templ, *src_view; + struct pipe_box dstbox; assert(dst && src); assert(src->target < PIPE_MAX_TEXTURE_TYPES); + u_box_3d(dstx, dsty, dstz, abs(srcbox->width), abs(srcbox->height), + abs(srcbox->depth), &dstbox); + /* Initialize the surface. */ - util_blitter_default_dst_texture(&dst_templ, dst, dst_level, dstz, srcbox); + util_blitter_default_dst_texture(&dst_templ, dst, dst_level, dstz); dst_view = pipe->create_surface(pipe, dst, &dst_templ); /* Initialize the sampler view. */ @@ -1189,8 +1217,7 @@ void util_blitter_copy_texture(struct blitter_context *blitter, src_view = pipe->create_sampler_view(pipe, src, &src_templ); /* Copy. */ - util_blitter_blit_generic(blitter, dst_view, dstx, dsty, - abs(srcbox->width), abs(srcbox->height), + util_blitter_blit_generic(blitter, dst_view, &dstbox, src_view, srcbox, src->width0, src->height0, mask, PIPE_TEX_FILTER_NEAREST, NULL, copy_all_samples); @@ -1201,8 +1228,7 @@ void util_blitter_copy_texture(struct blitter_context *blitter, void util_blitter_blit_generic(struct blitter_context *blitter, struct pipe_surface *dst, - int dstx, int dsty, - unsigned dst_width, unsigned dst_height, + const struct pipe_box *dstbox, struct pipe_sampler_view *src, const struct pipe_box *srcbox, unsigned src_width0, unsigned src_height0, @@ -1214,6 +1240,7 @@ void util_blitter_blit_generic(struct blitter_context *blitter, struct pipe_context *pipe = ctx->base.pipe; struct pipe_framebuffer_state fb_state; enum pipe_texture_target src_target = src->texture->target; + unsigned src_samples = src->texture->nr_samples; boolean has_depth, has_stencil, has_color; boolean blit_stencil, blit_depth, blit_color; void *sampler_state; @@ -1238,9 +1265,6 @@ void util_blitter_blit_generic(struct blitter_context *blitter, return; } - /* XXX should handle 3d regions */ - assert(srcbox->depth == 1); - /* Check whether the states are properly saved. */ blitter_set_running_flag(ctx); blitter_check_saved_vertex_states(ctx); @@ -1252,6 +1276,9 @@ void util_blitter_blit_generic(struct blitter_context *blitter, /* Initialize framebuffer state. */ fb_state.width = dst->width; fb_state.height = dst->height; + fb_state.nr_cbufs = blit_depth || blit_stencil ? 0 : 1; + fb_state.cbufs[0] = NULL; + fb_state.zsbuf = NULL; if (blit_depth || blit_stencil) { pipe->bind_blend_state(pipe, ctx->blend[0]); @@ -1260,41 +1287,36 @@ void util_blitter_blit_generic(struct blitter_context *blitter, pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_stencil); ctx->bind_fs_state(pipe, - blitter_get_fs_texfetch_depthstencil(ctx, src->texture->target, - src->texture->nr_samples)); + blitter_get_fs_texfetch_depthstencil(ctx, src_target, + src_samples)); } else if (blit_depth) { pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_keep_stencil); ctx->bind_fs_state(pipe, - blitter_get_fs_texfetch_depth(ctx, src->texture->target, - src->texture->nr_samples)); + blitter_get_fs_texfetch_depth(ctx, src_target, + src_samples)); } else { /* is_stencil */ pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_write_stencil); ctx->bind_fs_state(pipe, - blitter_get_fs_texfetch_stencil(ctx, src->texture->target, - src->texture->nr_samples)); + blitter_get_fs_texfetch_stencil(ctx, src_target, + src_samples)); } - fb_state.nr_cbufs = 0; - fb_state.zsbuf = dst; } else { pipe->bind_blend_state(pipe, ctx->blend[mask & PIPE_MASK_RGBA]); pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil); ctx->bind_fs_state(pipe, - blitter_get_fs_texfetch_col(ctx, src->texture->target, - src->texture->nr_samples)); - - fb_state.nr_cbufs = 1; - fb_state.cbufs[0] = dst; - fb_state.zsbuf = 0; + blitter_get_fs_texfetch_col(ctx, src_target, + src_samples)); } /* Set the linear filter only for scaled color non-MSAA blits. */ if (filter == PIPE_TEX_FILTER_LINEAR && !blit_depth && !blit_stencil && - src->texture->nr_samples <= 1 && - (dst_width != abs(srcbox->width) || dst_height != abs(srcbox->height))) { + src_samples <= 1 && + (dstbox->width != abs(srcbox->width) || + dstbox->height != abs(srcbox->height))) { sampler_state = ctx->sampler_state_linear; } else { sampler_state = ctx->sampler_state; @@ -1339,8 +1361,6 @@ void util_blitter_blit_generic(struct blitter_context *blitter, } pipe->bind_vertex_elements_state(pipe, ctx->velem_state); - pipe->set_framebuffer_state(pipe, &fb_state); - if (scissor) { pipe->set_scissor_state(pipe, scissor); } @@ -1351,7 +1371,7 @@ void util_blitter_blit_generic(struct blitter_context *blitter, if ((src_target == PIPE_TEXTURE_1D || src_target == PIPE_TEXTURE_2D || src_target == PIPE_TEXTURE_RECT) && - src->texture->nr_samples <= 1) { + src_samples <= 1) { /* Draw the quad with the draw_rectangle callback. */ /* Set texture coordinates. - use a pipe color union @@ -1363,35 +1383,72 @@ void util_blitter_blit_generic(struct blitter_context *blitter, get_texcoords(src, src_width0, src_height0, srcbox->x, srcbox->y, srcbox->x+srcbox->width, srcbox->y+srcbox->height, coord.f); + /* Set framebuffer state. */ + if (blit_depth || blit_stencil) { + fb_state.zsbuf = dst; + } else { + fb_state.cbufs[0] = dst; + } + pipe->set_framebuffer_state(pipe, &fb_state); + /* Draw. */ pipe->set_sample_mask(pipe, ~0); - blitter->draw_rectangle(blitter, dstx, dsty, - dstx+dst_width, dsty+dst_height, 0, + blitter->draw_rectangle(blitter, dstbox->x, dstbox->y, + dstbox->x + dstbox->width, + dstbox->y + dstbox->height, 0, UTIL_BLITTER_ATTRIB_TEXCOORD, &coord); } else { /* Draw the quad with the generic codepath. */ - if (copy_all_samples && - src->texture->nr_samples == dst->texture->nr_samples && - dst->texture->nr_samples > 1) { - /* MSAA copy. */ - unsigned i, max_sample = MAX2(dst->texture->nr_samples, 1) - 1; - - for (i = 0; i <= max_sample; i++) { - pipe->set_sample_mask(pipe, 1 << i); - blitter_set_texcoords(ctx, src, src_width0, src_height0, srcbox->z, - i, srcbox->x, srcbox->y, + int z; + for (z = 0; z < dstbox->depth; z++) { + struct pipe_surface *old; + + /* Set framebuffer state. */ + if (blit_depth || blit_stencil) { + fb_state.zsbuf = dst; + } else { + fb_state.cbufs[0] = dst; + } + pipe->set_framebuffer_state(pipe, &fb_state); + + /* See if we need to blit a multisample or singlesample buffer. */ + if (copy_all_samples && + src_samples == dst->texture->nr_samples && + dst->texture->nr_samples > 1) { + unsigned i, max_sample = MAX2(dst->texture->nr_samples, 1) - 1; + + for (i = 0; i <= max_sample; i++) { + pipe->set_sample_mask(pipe, 1 << i); + blitter_set_texcoords(ctx, src, src_width0, src_height0, + srcbox->z + z, + i, srcbox->x, srcbox->y, + srcbox->x + srcbox->width, + srcbox->y + srcbox->height); + blitter_draw(ctx, dstbox->x, dstbox->y, + dstbox->x + dstbox->width, + dstbox->y + dstbox->height, 0); + } + } else { + pipe->set_sample_mask(pipe, ~0); + blitter_set_texcoords(ctx, src, src_width0, src_height0, + srcbox->z + z, 0, + srcbox->x, srcbox->y, srcbox->x + srcbox->width, srcbox->y + srcbox->height); - blitter_draw(ctx, dstx, dsty, - dstx+dst_width, dsty+dst_height, 0); + blitter_draw(ctx, dstbox->x, dstbox->y, + dstbox->x + dstbox->width, + dstbox->y + dstbox->height, 0); + } + + /* Get the next surface or (if this is the last iteration) + * just unreference the last one. */ + old = dst; + if (z < dstbox->depth-1) { + dst = ctx->base.get_next_surface_layer(ctx->base.pipe, dst); + } + if (z) { + pipe_surface_reference(&old, NULL); } - } else { - pipe->set_sample_mask(pipe, ~0); - blitter_set_texcoords(ctx, src, src_width0, src_height0, srcbox->z, 0, - srcbox->x, srcbox->y, - srcbox->x + srcbox->width, - srcbox->y + srcbox->height); - blitter_draw(ctx, dstx, dsty, dstx+dst_width, dsty+dst_height, 0); } } @@ -1419,7 +1476,7 @@ util_blitter_blit(struct blitter_context *blitter, /* Initialize the surface. */ util_blitter_default_dst_texture(&dst_templ, dst, info->dst.level, - info->dst.box.z, &info->src.box); + info->dst.box.z); dst_templ.format = info->dst.format; dst_view = pipe->create_surface(pipe, dst, &dst_templ); @@ -1429,9 +1486,7 @@ util_blitter_blit(struct blitter_context *blitter, src_view = pipe->create_sampler_view(pipe, src, &src_templ); /* Copy. */ - util_blitter_blit_generic(blitter, dst_view, - info->dst.box.x, info->dst.box.y, - info->dst.box.width, info->dst.box.height, + util_blitter_blit_generic(blitter, dst_view, &info->dst.box, src_view, &info->src.box, src->width0, src->height0, info->mask, info->filter, info->scissor_enable ? &info->scissor : NULL, TRUE); @@ -1761,7 +1816,8 @@ void util_blitter_custom_color(struct blitter_context *blitter, blitter_disable_render_cond(ctx); /* bind states */ - pipe->bind_blend_state(pipe, custom_blend); + pipe->bind_blend_state(pipe, custom_blend ? custom_blend + : ctx->blend[PIPE_MASK_RGBA]); pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil); ctx->bind_fs_state(pipe, blitter_get_fs_col(ctx, 1, FALSE)); pipe->bind_vertex_elements_state(pipe, ctx->velem_state); diff --git a/mesalib/src/gallium/auxiliary/util/u_blitter.h b/mesalib/src/gallium/auxiliary/util/u_blitter.h index 0b5e4aa45..20e69ed5b 100644 --- a/mesalib/src/gallium/auxiliary/util/u_blitter.h +++ b/mesalib/src/gallium/auxiliary/util/u_blitter.h @@ -83,6 +83,15 @@ struct blitter_context enum blitter_attrib_type type, const union pipe_color_union *color); + /** + * Get the next surface layer for the pipe surface, i.e. make a copy + * of the surface and increment the first and last layer by 1. + * + * This callback is exposed, so that drivers can override it if needed. + */ + struct pipe_surface *(*get_next_surface_layer)(struct pipe_context *pipe, + struct pipe_surface *surf); + /* Whether the blitter is running. */ boolean running; @@ -217,14 +226,15 @@ void util_blitter_copy_texture(struct blitter_context *blitter, boolean copy_all_samples); /** - * Same as util_blitter_copy_texture with the capabilities of util_blitter_blit, - * but dst and src are pipe_surface and pipe_sampler_view, respectively. - * The mipmap level and dstz are part of the views. + * This is a generic implementation of pipe->blit, which accepts + * sampler/surface views instead of resources. + * + * The layer and mipmap level are specified by the views. * * Drivers can use this to change resource properties (like format, width, * height) by changing how the views interpret them, instead of changing - * pipe_resource directly. This is usually needed to accelerate copying of - * compressed formats. + * pipe_resource directly. This is used to blit resources of formats which + * are not renderable. * * src_width0 and src_height0 are sampler_view-private properties that * override pipe_resource. The blitter uses them for computation of texture @@ -236,8 +246,7 @@ void util_blitter_copy_texture(struct blitter_context *blitter, */ void util_blitter_blit_generic(struct blitter_context *blitter, struct pipe_surface *dst, - int dstx, int dsty, - unsigned dst_width, unsigned dst_height, + const struct pipe_box *dstbox, struct pipe_sampler_view *src, const struct pipe_box *srcbox, unsigned src_width0, unsigned src_height0, @@ -255,8 +264,7 @@ void util_blitter_blit(struct blitter_context *blitter, void util_blitter_default_dst_texture(struct pipe_surface *dst_templ, struct pipe_resource *dst, unsigned dstlevel, - unsigned dstz, - const struct pipe_box *srcbox); + unsigned dstz); /** * Helper function to initialize a view for copy_texture_view. diff --git a/mesalib/src/gallium/auxiliary/util/u_dump_state.c b/mesalib/src/gallium/auxiliary/util/u_dump_state.c index 09faffe73..d7df5b495 100644 --- a/mesalib/src/gallium/auxiliary/util/u_dump_state.c +++ b/mesalib/src/gallium/auxiliary/util/u_dump_state.c @@ -681,13 +681,14 @@ util_dump_transfer(FILE *stream, const struct pipe_transfer *state) util_dump_struct_begin(stream, "pipe_transfer"); util_dump_member(stream, ptr, state, resource); - /*util_dump_member(stream, uint, state, box);*/ - + util_dump_member(stream, uint, state, level); + util_dump_member(stream, uint, state, usage); + util_dump_member_begin(stream, "box"); + util_dump_box(stream, &state->box); + util_dump_member_end(stream); util_dump_member(stream, uint, state, stride); util_dump_member(stream, uint, state, layer_stride); - /*util_dump_member(stream, ptr, state, data);*/ - util_dump_struct_end(stream); } diff --git a/mesalib/src/gallium/auxiliary/util/u_format_zs.c b/mesalib/src/gallium/auxiliary/util/u_format_zs.c index 816ef1420..ed45c52f9 100644 --- a/mesalib/src/gallium/auxiliary/util/u_format_zs.c +++ b/mesalib/src/gallium/auxiliary/util/u_format_zs.c @@ -72,7 +72,7 @@ static INLINE uint16_t z32_float_to_z16_unorm(float z) { const float scale = 0xffff; - return (uint16_t)(z * scale); + return (uint16_t)(z * scale + 0.5f); } static INLINE float diff --git a/mesalib/src/gallium/auxiliary/util/u_inlines.h b/mesalib/src/gallium/auxiliary/util/u_inlines.h index 582aacdca..2ff90c982 100644 --- a/mesalib/src/gallium/auxiliary/util/u_inlines.h +++ b/mesalib/src/gallium/auxiliary/util/u_inlines.h @@ -421,6 +421,24 @@ pipe_transfer_map(struct pipe_context *context, &box, transfer); } +static INLINE void * +pipe_transfer_map_3d(struct pipe_context *context, + struct pipe_resource *resource, + unsigned level, + enum pipe_transfer_usage usage, + unsigned x, unsigned y, unsigned z, + unsigned w, unsigned h, unsigned d, + struct pipe_transfer **transfer) +{ + struct pipe_box box; + u_box_3d(x, y, z, w, h, d, &box); + return context->transfer_map(context, + resource, + level, + usage, + &box, transfer); +} + static INLINE void pipe_transfer_unmap( struct pipe_context *context, struct pipe_transfer *transfer ) diff --git a/mesalib/src/gallium/auxiliary/util/u_surface.c b/mesalib/src/gallium/auxiliary/util/u_surface.c index 5e771c950..37f48154f 100644 --- a/mesalib/src/gallium/auxiliary/util/u_surface.c +++ b/mesalib/src/gallium/auxiliary/util/u_surface.c @@ -56,61 +56,6 @@ u_surface_default_template(struct pipe_surface *surf, surf->format = texture->format; } -/** - * Helper to quickly create an RGBA rendering surface of a certain size. - * \param textureOut returns the new texture - * \param surfaceOut returns the new surface - * \return TRUE for success, FALSE if failure - */ -boolean -util_create_rgba_texture(struct pipe_context *pipe, - uint width, uint height, uint bind, - struct pipe_resource **textureOut) -{ - static const enum pipe_format rgbaFormats[] = { - PIPE_FORMAT_B8G8R8A8_UNORM, - PIPE_FORMAT_A8R8G8B8_UNORM, - PIPE_FORMAT_A8B8G8R8_UNORM, - PIPE_FORMAT_NONE - }; - const uint target = PIPE_TEXTURE_2D; - enum pipe_format format = PIPE_FORMAT_NONE; - struct pipe_resource templ; - struct pipe_surface surf_templ; - struct pipe_screen *screen = pipe->screen; - uint i; - - /* Choose surface format */ - for (i = 0; rgbaFormats[i]; i++) { - if (screen->is_format_supported(screen, rgbaFormats[i], - target, 0, bind)) { - format = rgbaFormats[i]; - break; - } - } - if (format == PIPE_FORMAT_NONE) - return FALSE; /* unable to get an rgba format!?! */ - - /* create texture */ - memset(&templ, 0, sizeof(templ)); - templ.target = target; - templ.format = format; - templ.last_level = 0; - templ.width0 = width; - templ.height0 = height; - templ.depth0 = 1; - templ.array_size = 1; - templ.bind = bind; - - *textureOut = screen->resource_create(screen, &templ); - if (!*textureOut) - return FALSE; - - /* create surface */ - u_surface_default_template(&surf_templ, *textureOut); - return TRUE; -} - /** * Copy 2D rect from one place to another. diff --git a/mesalib/src/gallium/auxiliary/util/u_surface.h b/mesalib/src/gallium/auxiliary/util/u_surface.h index fe950c818..d6184acbd 100644 --- a/mesalib/src/gallium/auxiliary/util/u_surface.h +++ b/mesalib/src/gallium/auxiliary/util/u_surface.h @@ -44,12 +44,6 @@ extern void u_surface_default_template(struct pipe_surface *view, const struct pipe_resource *texture); -extern boolean -util_create_rgba_texture(struct pipe_context *ctx, - uint width, uint height, uint bind, - struct pipe_resource **textureOut); - - extern void util_copy_rect(ubyte * dst, enum pipe_format format, unsigned dst_stride, unsigned dst_x, unsigned dst_y, diff --git a/mesalib/src/gallium/auxiliary/util/u_tile.c b/mesalib/src/gallium/auxiliary/util/u_tile.c index f4b5cad0e..6c618a674 100644 --- a/mesalib/src/gallium/auxiliary/util/u_tile.c +++ b/mesalib/src/gallium/auxiliary/util/u_tile.c @@ -678,6 +678,28 @@ pipe_get_tile_z(struct pipe_transfer *pt, } } break; + case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT: + { + const float *ptrc = (const float *)(map + y * pt->stride + x*8); + for (i = 0; i < h; i++) { + for (j = 0; j < w; j++) { + /* convert float Z to 32-bit Z */ + if (ptrc[j] <= 0.0) { + pDest[j*2] = 0; + } + else if (ptrc[j] >= 1.0) { + pDest[j*2] = 0xffffffff; + } + else { + double z = ptrc[j] * 0xffffffff; + pDest[j*2] = (uint) z; + } + } + pDest += dstStride; + ptrc += pt->stride/4; + } + } + break; default: assert(0); } @@ -779,7 +801,7 @@ pipe_put_tile_z(struct pipe_transfer *pt, break; case PIPE_FORMAT_Z32_FLOAT: { - float *pDest = (float *) (map + y * pt->stride + x*2); + float *pDest = (float *) (map + y * pt->stride + x*4); for (i = 0; i < h; i++) { for (j = 0; j < w; j++) { /* convert 32-bit integer Z to float Z */ @@ -791,6 +813,20 @@ pipe_put_tile_z(struct pipe_transfer *pt, } } break; + case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT: + { + float *pDest = (float *) (map + y * pt->stride + x*8); + for (i = 0; i < h; i++) { + for (j = 0; j < w; j++) { + /* convert 32-bit integer Z to float Z */ + const double scale = 1.0 / 0xffffffffU; + pDest[j*2] = ptrc[j] * scale; + } + pDest += pt->stride/4; + ptrc += srcStride; + } + } + break; default: assert(0); } diff --git a/mesalib/src/glsl/glcpp/Makefile.am b/mesalib/src/glsl/glcpp/Makefile.am index d8d39d295..1efc9dc1a 100644 --- a/mesalib/src/glsl/glcpp/Makefile.am +++ b/mesalib/src/glsl/glcpp/Makefile.am @@ -28,6 +28,7 @@ AM_CFLAGS = \ -I$(top_srcdir)/include \ -I$(top_srcdir)/src/mapi \ -I$(top_srcdir)/src/mesa/ \ + $(VISIBILITY_CFLAGS) \ $(LIBRARY_INCLUDES) \ $(DEFINES) \ $(LIBRARY_DEFINES) \ diff --git a/mesalib/src/glsl/ir_uniform.h b/mesalib/src/glsl/ir_uniform.h index 913c53773..30e6f260d 100644 --- a/mesalib/src/glsl/ir_uniform.h +++ b/mesalib/src/glsl/ir_uniform.h @@ -80,6 +80,10 @@ struct gl_uniform_driver_storage { struct gl_uniform_storage { char *name; + /** Type of this uniform data stored. + * + * In the case of an array, it's the type of a single array element. + */ const struct glsl_type *type; /** diff --git a/mesalib/src/mesa/drivers/common/meta.c b/mesalib/src/mesa/drivers/common/meta.c index ac036eaac..d211fda9d 100644 --- a/mesalib/src/mesa/drivers/common/meta.c +++ b/mesalib/src/mesa/drivers/common/meta.c @@ -474,8 +474,7 @@ _mesa_meta_begin(struct gl_context *ctx, GLbitfield state) * able to change other state. */ save->TransformFeedbackNeedsResume = - ctx->TransformFeedback.CurrentObject->Active && - !ctx->TransformFeedback.CurrentObject->Paused; + _mesa_is_xfb_active_and_unpaused(ctx); if (save->TransformFeedbackNeedsResume) _mesa_PauseTransformFeedback(); diff --git a/mesalib/src/mesa/main/api_validate.c b/mesalib/src/mesa/main/api_validate.c index e47db23e0..133fb6370 100644 --- a/mesalib/src/mesa/main/api_validate.c +++ b/mesalib/src/mesa/main/api_validate.c @@ -32,6 +32,7 @@ #include "mtypes.h" #include "enums.h" #include "vbo/vbo.h" +#include "transformfeedback.h" #include <stdbool.h> @@ -252,8 +253,7 @@ _mesa_valid_prim_mode(struct gl_context *ctx, GLenum mode, const char *name) * current transform feedback state as given by table X.1. * */ - if (ctx->TransformFeedback.CurrentObject->Active && - !ctx->TransformFeedback.CurrentObject->Paused) { + if (_mesa_is_xfb_active_and_unpaused(ctx)) { GLboolean pass = GL_TRUE; switch (mode) { @@ -316,6 +316,19 @@ _mesa_validate_DrawElements(struct gl_context *ctx, ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); FLUSH_CURRENT(ctx, 0); + /* From the GLES3 specification, section 2.14.2 (Transform Feedback + * Primitive Capture): + * + * The error INVALID_OPERATION is also generated by DrawElements, + * DrawElementsInstanced, and DrawRangeElements while transform feedback + * is active and not paused, regardless of mode. + */ + if (_mesa_is_gles3(ctx) && _mesa_is_xfb_active_and_unpaused(ctx)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glDrawElements(transform feedback active)"); + return GL_FALSE; + } + if (count <= 0) { if (count < 0) _mesa_error(ctx, GL_INVALID_VALUE, "glDrawElements(count)" ); @@ -434,6 +447,19 @@ _mesa_validate_DrawRangeElements(struct gl_context *ctx, GLenum mode, ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); FLUSH_CURRENT(ctx, 0); + /* From the GLES3 specification, section 2.14.2 (Transform Feedback + * Primitive Capture): + * + * The error INVALID_OPERATION is also generated by DrawElements, + * DrawElementsInstanced, and DrawRangeElements while transform feedback + * is active and not paused, regardless of mode. + */ + if (_mesa_is_gles3(ctx) && _mesa_is_xfb_active_and_unpaused(ctx)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glDrawElements(transform feedback active)"); + return GL_FALSE; + } + if (count <= 0) { if (count < 0) _mesa_error(ctx, GL_INVALID_VALUE, "glDrawRangeElements(count)" ); @@ -486,6 +512,8 @@ GLboolean _mesa_validate_DrawArrays(struct gl_context *ctx, GLenum mode, GLint start, GLsizei count) { + struct gl_transform_feedback_object *xfb_obj + = ctx->TransformFeedback.CurrentObject; ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); FLUSH_CURRENT(ctx, 0); @@ -507,6 +535,29 @@ _mesa_validate_DrawArrays(struct gl_context *ctx, return GL_FALSE; } + /* From the GLES3 specification, section 2.14.2 (Transform Feedback + * Primitive Capture): + * + * The error INVALID_OPERATION is generated by DrawArrays and + * DrawArraysInstanced if recording the vertices of a primitive to the + * buffer objects being used for transform feedback purposes would result + * in either exceeding the limits of any buffer object’s size, or in + * exceeding the end position offset + size − 1, as set by + * BindBufferRange. + * + * This is in contrast to the behaviour of desktop GL, where the extra + * primitives are silently dropped from the transform feedback buffer. + */ + if (_mesa_is_gles3(ctx) && _mesa_is_xfb_active_and_unpaused(ctx)) { + size_t prim_count = vbo_count_tessellated_primitives(mode, count, 1); + if (xfb_obj->GlesRemainingPrims < prim_count) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glDrawArrays(exceeds transform feedback size)"); + return GL_FALSE; + } + xfb_obj->GlesRemainingPrims -= prim_count; + } + return GL_TRUE; } @@ -515,6 +566,8 @@ GLboolean _mesa_validate_DrawArraysInstanced(struct gl_context *ctx, GLenum mode, GLint first, GLsizei count, GLsizei numInstances) { + struct gl_transform_feedback_object *xfb_obj + = ctx->TransformFeedback.CurrentObject; ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); FLUSH_CURRENT(ctx, 0); @@ -550,6 +603,30 @@ _mesa_validate_DrawArraysInstanced(struct gl_context *ctx, GLenum mode, GLint fi return GL_FALSE; } + /* From the GLES3 specification, section 2.14.2 (Transform Feedback + * Primitive Capture): + * + * The error INVALID_OPERATION is generated by DrawArrays and + * DrawArraysInstanced if recording the vertices of a primitive to the + * buffer objects being used for transform feedback purposes would result + * in either exceeding the limits of any buffer object’s size, or in + * exceeding the end position offset + size − 1, as set by + * BindBufferRange. + * + * This is in contrast to the behaviour of desktop GL, where the extra + * primitives are silently dropped from the transform feedback buffer. + */ + if (_mesa_is_gles3(ctx) && _mesa_is_xfb_active_and_unpaused(ctx)) { + size_t prim_count + = vbo_count_tessellated_primitives(mode, count, numInstances); + if (xfb_obj->GlesRemainingPrims < prim_count) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glDrawArraysInstanced(exceeds transform feedback size)"); + return GL_FALSE; + } + xfb_obj->GlesRemainingPrims -= prim_count; + } + return GL_TRUE; } @@ -563,6 +640,19 @@ _mesa_validate_DrawElementsInstanced(struct gl_context *ctx, ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); FLUSH_CURRENT(ctx, 0); + /* From the GLES3 specification, section 2.14.2 (Transform Feedback + * Primitive Capture): + * + * The error INVALID_OPERATION is also generated by DrawElements, + * DrawElementsInstanced, and DrawRangeElements while transform feedback + * is active and not paused, regardless of mode. + */ + if (_mesa_is_gles3(ctx) && _mesa_is_xfb_active_and_unpaused(ctx)) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glDrawElements(transform feedback active)"); + return GL_FALSE; + } + if (count <= 0) { if (count < 0) _mesa_error(ctx, GL_INVALID_VALUE, diff --git a/mesalib/src/mesa/main/arrayobj.c b/mesalib/src/mesa/main/arrayobj.c index a909e0eff..032af43b5 100644 --- a/mesalib/src/mesa/main/arrayobj.c +++ b/mesalib/src/mesa/main/arrayobj.c @@ -373,7 +373,7 @@ bind_vertex_array(struct gl_context *ctx, GLuint id, GLboolean genRequired) save_array_object(ctx, newObj); } - if (!newObj->_Used) { + if (!newObj->EverBound) { /* The "Interactions with APPLE_vertex_array_object" section of the * GL_ARB_vertex_array_object spec says: * @@ -381,7 +381,7 @@ bind_vertex_array(struct gl_context *ctx, GLuint id, GLboolean genRequired) * BindVertexArrayAPPLE, determines the semantic of the object." */ newObj->ARBsemantics = genRequired; - newObj->_Used = GL_TRUE; + newObj->EverBound = GL_TRUE; } } @@ -551,6 +551,8 @@ _mesa_IsVertexArray( GLuint id ) return GL_FALSE; obj = lookup_arrayobj(ctx, id); + if (obj == NULL) + return GL_FALSE; - return (obj != NULL) ? GL_TRUE : GL_FALSE; + return obj->EverBound; } diff --git a/mesalib/src/mesa/main/buffers.c b/mesalib/src/mesa/main/buffers.c index 76f0d4671..d10a57394 100644 --- a/mesalib/src/mesa/main/buffers.c +++ b/mesalib/src/mesa/main/buffers.c @@ -532,8 +532,8 @@ _mesa_ReadBuffer(GLenum buffer) if (MESA_VERBOSE & VERBOSE_API) _mesa_debug(ctx, "glReadBuffer %s\n", _mesa_lookup_enum_by_nr(buffer)); - if (_mesa_is_user_fbo(fb) && buffer == GL_NONE) { - /* This is legal for user-created framebuffer objects */ + if (buffer == GL_NONE) { + /* This is legal--it means that no buffer should be bound for reading. */ srcBuffer = -1; } else { diff --git a/mesalib/src/mesa/main/fbobject.c b/mesalib/src/mesa/main/fbobject.c index ce77b9f77..281cdd05c 100644 --- a/mesalib/src/mesa/main/fbobject.c +++ b/mesalib/src/mesa/main/fbobject.c @@ -1169,35 +1169,23 @@ _mesa_base_fbo_format(struct gl_context *ctx, GLenum internalFormat) return ctx->API != API_OPENGLES && ctx->Extensions.ARB_texture_rg ? GL_RG : 0; /* signed normalized texture formats */ - case GL_R8_SNORM: - return ctx->Version >= 30 - || (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.EXT_texture_snorm) - ? GL_RED : 0; case GL_RED_SNORM: + case GL_R8_SNORM: case GL_R16_SNORM: return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_snorm ? GL_RED : 0; - case GL_RG8_SNORM: - return ctx->Version >= 30 - || (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.EXT_texture_snorm) - ? GL_RG : 0; case GL_RG_SNORM: + case GL_RG8_SNORM: case GL_RG16_SNORM: return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_snorm ? GL_RG : 0; - case GL_RGB8_SNORM: - return ctx->Version >= 30 - || (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.EXT_texture_snorm) - ? GL_RGB : 0; case GL_RGB_SNORM: + case GL_RGB8_SNORM: case GL_RGB16_SNORM: return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_snorm ? GL_RGB : 0; - case GL_RGBA8_SNORM: - return ctx->Version >= 30 - || (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.EXT_texture_snorm) - ? GL_RGBA : 0; case GL_RGBA_SNORM: + case GL_RGBA8_SNORM: case GL_RGBA16_SNORM: return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_snorm ? GL_RGBA : 0; @@ -1207,24 +1195,6 @@ _mesa_base_fbo_format(struct gl_context *ctx, GLenum internalFormat) return ctx->API == API_OPENGL_COMPAT && ctx->Extensions.EXT_texture_snorm && ctx->Extensions.ARB_framebuffer_object ? GL_ALPHA : 0; - case GL_LUMINANCE_SNORM: - case GL_LUMINANCE8_SNORM: - case GL_LUMINANCE16_SNORM: - return ctx->API == API_OPENGL_COMPAT && - ctx->Extensions.EXT_texture_snorm && - ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE : 0; - case GL_LUMINANCE_ALPHA_SNORM: - case GL_LUMINANCE8_ALPHA8_SNORM: - case GL_LUMINANCE16_ALPHA16_SNORM: - return ctx->API == API_OPENGL_COMPAT && - ctx->Extensions.EXT_texture_snorm && - ctx->Extensions.ARB_framebuffer_object ? GL_LUMINANCE_ALPHA : 0; - case GL_INTENSITY_SNORM: - case GL_INTENSITY8_SNORM: - case GL_INTENSITY16_SNORM: - return ctx->API == API_OPENGL_COMPAT && - ctx->Extensions.EXT_texture_snorm && - ctx->Extensions.ARB_framebuffer_object ? GL_INTENSITY : 0; case GL_R16F: case GL_R32F: return ctx->Version >= 30 @@ -1291,10 +1261,8 @@ _mesa_base_fbo_format(struct gl_context *ctx, GLenum internalFormat) case GL_RGB8I_EXT: case GL_RGB16I_EXT: case GL_RGB32I_EXT: - return ctx->Version >= 30 - || (_mesa_is_desktop_gl(ctx) && - ctx->Extensions.EXT_texture_integer) ? GL_RGB : 0; - + return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_integer + ? GL_RGB : 0; case GL_R8UI: case GL_R8I: case GL_R16UI: diff --git a/mesalib/src/mesa/main/get.c b/mesalib/src/mesa/main/get.c index f3dbda2d3..273a79f7f 100644 --- a/mesalib/src/mesa/main/get.c +++ b/mesalib/src/mesa/main/get.c @@ -1574,7 +1574,8 @@ find_value_indexed(const char *func, GLenum pname, GLuint index, union value *v) goto invalid_value; if (!ctx->Extensions.EXT_transform_feedback) goto invalid_enum; - v->value_int64 = ctx->TransformFeedback.CurrentObject->Size[index]; + v->value_int64 + = ctx->TransformFeedback.CurrentObject->RequestedSize[index]; return TYPE_INT64; case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: diff --git a/mesalib/src/mesa/main/mtypes.h b/mesalib/src/mesa/main/mtypes.h index 67eaadd9f..7c513a1c5 100644 --- a/mesalib/src/mesa/main/mtypes.h +++ b/mesalib/src/mesa/main/mtypes.h @@ -1595,7 +1595,7 @@ struct gl_array_object /** * Has this array object been bound? */ - GLboolean _Used; + GLboolean EverBound; /** Vertex attribute arrays */ struct gl_client_array VertexAttrib[VERT_ATTRIB_MAX]; @@ -1807,6 +1807,18 @@ struct gl_transform_feedback_object GLboolean Paused; /**< Is transform feedback paused? */ GLboolean EndedAnytime; /**< Has EndTransformFeedback been called at least once? */ + GLboolean EverBound; /**< Has this object been bound? */ + + /** + * GLES: if Active is true, remaining number of primitives which can be + * rendered without overflow. This is necessary to track because GLES + * requires us to generate INVALID_OPERATION if a call to glDrawArrays or + * glDrawArraysInstanced would overflow transform feedback buffers. + * Undefined if Active is false. + * + * Not tracked for desktop GL since it's unnecessary. + */ + unsigned GlesRemainingPrims; /** The feedback buffers */ GLuint BufferNames[MAX_FEEDBACK_BUFFERS]; @@ -1814,8 +1826,19 @@ struct gl_transform_feedback_object /** Start of feedback data in dest buffer */ GLintptr Offset[MAX_FEEDBACK_BUFFERS]; - /** Max data to put into dest buffer (in bytes) */ + + /** + * Max data to put into dest buffer (in bytes). Computed based on + * RequestedSize and the actual size of the buffer. + */ GLsizeiptr Size[MAX_FEEDBACK_BUFFERS]; + + /** + * Size that was specified when the buffer was bound. If the buffer was + * bound with glBindBufferBase() or glBindBufferOffsetEXT(), this value is + * zero. + */ + GLsizeiptr RequestedSize[MAX_FEEDBACK_BUFFERS]; }; diff --git a/mesalib/src/mesa/main/pbo.c b/mesalib/src/mesa/main/pbo.c index c73d7492f..0dc4c04eb 100644 --- a/mesalib/src/mesa/main/pbo.c +++ b/mesalib/src/mesa/main/pbo.c @@ -342,7 +342,8 @@ _mesa_validate_pbo_teximage(struct gl_context *ctx, GLuint dimensions, } if (!_mesa_validate_pbo_access(dimensions, unpack, width, height, depth, format, type, INT_MAX, pixels)) { - _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(invalid PBO access)"); + _mesa_error(ctx, GL_INVALID_OPERATION, "%s%uD(invalid PBO access)", + funcName, dimensions); return NULL; } @@ -351,7 +352,8 @@ _mesa_validate_pbo_teximage(struct gl_context *ctx, GLuint dimensions, GL_MAP_READ_BIT, unpack->BufferObj); if (!buf) { - _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(PBO is mapped)"); + _mesa_error(ctx, GL_INVALID_OPERATION, "%s%uD(PBO is mapped)", funcName, + dimensions); return NULL; } @@ -368,7 +370,8 @@ _mesa_validate_pbo_teximage(struct gl_context *ctx, GLuint dimensions, */ const GLvoid * _mesa_validate_pbo_compressed_teximage(struct gl_context *ctx, - GLsizei imageSize, const GLvoid *pixels, + GLuint dimensions, GLsizei imageSize, + const GLvoid *pixels, const struct gl_pixelstore_attrib *packing, const char *funcName) { @@ -381,7 +384,8 @@ _mesa_validate_pbo_compressed_teximage(struct gl_context *ctx, if ((const GLubyte *) pixels + imageSize > ((const GLubyte *) 0) + packing->BufferObj->Size) { /* out of bounds read! */ - _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(invalid PBO access)"); + _mesa_error(ctx, GL_INVALID_OPERATION, "%s%uD(invalid PBO access)", + funcName, dimensions); return NULL; } @@ -390,7 +394,8 @@ _mesa_validate_pbo_compressed_teximage(struct gl_context *ctx, GL_MAP_READ_BIT, packing->BufferObj); if (!buf) { - _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(PBO is mapped"); + _mesa_error(ctx, GL_INVALID_OPERATION, "%s%uD(PBO is mapped)", funcName, + dimensions); return NULL; } diff --git a/mesalib/src/mesa/main/pbo.h b/mesalib/src/mesa/main/pbo.h index 00a6e617f..9eba33514 100644 --- a/mesalib/src/mesa/main/pbo.h +++ b/mesalib/src/mesa/main/pbo.h @@ -81,7 +81,8 @@ _mesa_validate_pbo_teximage(struct gl_context *ctx, GLuint dimensions, extern const GLvoid * _mesa_validate_pbo_compressed_teximage(struct gl_context *ctx, - GLsizei imageSize, const GLvoid *pixels, + GLuint dimensions, GLsizei imageSize, + const GLvoid *pixels, const struct gl_pixelstore_attrib *packing, const char *funcName); diff --git a/mesalib/src/mesa/main/samplerobj.c b/mesalib/src/mesa/main/samplerobj.c index 3c3bfffd4..773bebf26 100644 --- a/mesalib/src/mesa/main/samplerobj.c +++ b/mesalib/src/mesa/main/samplerobj.c @@ -110,7 +110,7 @@ _mesa_reference_sampler_object_(struct gl_context *ctx, /** * Initialize the fields of the given sampler object. */ -void +static void _mesa_init_sampler_object(struct gl_sampler_object *sampObj, GLuint name) { sampObj->Name = name; @@ -151,7 +151,7 @@ _mesa_new_sampler_object(struct gl_context *ctx, GLuint name) /** * Fallback for ctx->Driver.DeleteSamplerObject(); */ -void +static void _mesa_delete_sampler_object(struct gl_context *ctx, struct gl_sampler_object *sampObj) { @@ -606,6 +606,8 @@ _mesa_SamplerParameteri(GLuint sampler, GLenum pname, GLint param) GLuint res; GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + sampObj = _mesa_lookup_samplerobj(ctx, sampler); if (!sampObj) { _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameteri(sampler %u)", @@ -777,6 +779,8 @@ _mesa_SamplerParameteriv(GLuint sampler, GLenum pname, const GLint *params) GLuint res; GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + sampObj = _mesa_lookup_samplerobj(ctx, sampler); if (!sampObj) { _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameteriv(sampler %u)", @@ -956,6 +960,8 @@ _mesa_SamplerParameterIiv(GLuint sampler, GLenum pname, const GLint *params) GLuint res; GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + sampObj = _mesa_lookup_samplerobj(ctx, sampler); if (!sampObj) { _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameterIiv(sampler %u)", @@ -1042,6 +1048,8 @@ _mesa_SamplerParameterIuiv(GLuint sampler, GLenum pname, const GLuint *params) GLuint res; GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + sampObj = _mesa_lookup_samplerobj(ctx, sampler); if (!sampObj) { _mesa_error(ctx, GL_INVALID_VALUE, "glSamplerParameterIuiv(sampler %u)", @@ -1127,6 +1135,8 @@ _mesa_GetSamplerParameteriv(GLuint sampler, GLenum pname, GLint *params) struct gl_sampler_object *sampObj; GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + sampObj = _mesa_lookup_samplerobj(ctx, sampler); if (!sampObj) { _mesa_error(ctx, GL_INVALID_VALUE, "glGetSamplerParameteriv(sampler %u)", @@ -1205,6 +1215,8 @@ _mesa_GetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat *params) struct gl_sampler_object *sampObj; GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + sampObj = _mesa_lookup_samplerobj(ctx, sampler); if (!sampObj) { _mesa_error(ctx, GL_INVALID_VALUE, "glGetSamplerParameterfv(sampler %u)", @@ -1283,6 +1295,8 @@ _mesa_GetSamplerParameterIiv(GLuint sampler, GLenum pname, GLint *params) struct gl_sampler_object *sampObj; GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + sampObj = _mesa_lookup_samplerobj(ctx, sampler); if (!sampObj) { _mesa_error(ctx, GL_INVALID_VALUE, @@ -1362,6 +1376,8 @@ _mesa_GetSamplerParameterIuiv(GLuint sampler, GLenum pname, GLuint *params) struct gl_sampler_object *sampObj; GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + sampObj = _mesa_lookup_samplerobj(ctx, sampler); if (!sampObj) { _mesa_error(ctx, GL_INVALID_VALUE, diff --git a/mesalib/src/mesa/main/samplerobj.h b/mesalib/src/mesa/main/samplerobj.h index ecff032c9..dce7c6c30 100644 --- a/mesalib/src/mesa/main/samplerobj.h +++ b/mesalib/src/mesa/main/samplerobj.h @@ -63,17 +63,10 @@ _mesa_reference_sampler_object(struct gl_context *ctx, } -extern void -_mesa_init_sampler_object(struct gl_sampler_object *sampObj, GLuint name); - extern struct gl_sampler_object * _mesa_new_sampler_object(struct gl_context *ctx, GLuint name); extern void -_mesa_delete_sampler_object(struct gl_context *ctx, - struct gl_sampler_object *sampObj); - -extern void _mesa_init_sampler_object_functions(struct dd_function_table *driver); extern void diff --git a/mesalib/src/mesa/main/shaderapi.c b/mesalib/src/mesa/main/shaderapi.c index 53e9d0486..1f0002f6f 100644 --- a/mesalib/src/mesa/main/shaderapi.c +++ b/mesalib/src/mesa/main/shaderapi.c @@ -45,6 +45,7 @@ #include "main/mtypes.h" #include "main/shaderapi.h" #include "main/shaderobj.h" +#include "main/transformfeedback.h" #include "main/uniforms.h" #include "program/program.h" #include "program/prog_parameter.h" @@ -1383,12 +1384,10 @@ _mesa_UseProgram(GLhandleARB program) { GET_CURRENT_CONTEXT(ctx); struct gl_shader_program *shProg; - struct gl_transform_feedback_object *obj = - ctx->TransformFeedback.CurrentObject; ASSERT_OUTSIDE_BEGIN_END(ctx); - if (obj->Active && !obj->Paused) { + if (_mesa_is_xfb_active_and_unpaused(ctx)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glUseProgram(transform feedback active)"); return; @@ -1590,8 +1589,7 @@ _mesa_UseShaderProgramEXT(GLenum type, GLuint program) return; } - if (ctx->TransformFeedback.CurrentObject->Active && - !ctx->TransformFeedback.CurrentObject->Paused) { + if (_mesa_is_xfb_active_and_unpaused(ctx)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glUseShaderProgramEXT(transform feedback is active)"); return; diff --git a/mesalib/src/mesa/main/texcompress.c b/mesalib/src/mesa/main/texcompress.c index 33c580a88..077a967da 100644 --- a/mesalib/src/mesa/main/texcompress.c +++ b/mesalib/src/mesa/main/texcompress.c @@ -533,6 +533,10 @@ _mesa_get_compressed_fetch_func(gl_format format) case MESA_FORMAT_RGBA_DXT1: case MESA_FORMAT_RGBA_DXT3: case MESA_FORMAT_RGBA_DXT5: + case MESA_FORMAT_SRGB_DXT1: + case MESA_FORMAT_SRGBA_DXT1: + case MESA_FORMAT_SRGBA_DXT3: + case MESA_FORMAT_SRGBA_DXT5: return _mesa_get_dxt_fetch_func(format); case MESA_FORMAT_RGB_FXT1: case MESA_FORMAT_RGBA_FXT1: diff --git a/mesalib/src/mesa/main/texcompress_rgtc.c b/mesalib/src/mesa/main/texcompress_rgtc.c index fa9172aa2..1f8de25ec 100644 --- a/mesalib/src/mesa/main/texcompress_rgtc.c +++ b/mesalib/src/mesa/main/texcompress_rgtc.c @@ -364,9 +364,10 @@ fetch_signed_l_latc1(const GLubyte *map, const GLuint imageOffsets[], GLint rowStride, GLint i, GLint j, GLint k, GLfloat *texel) { - GLubyte red; + GLbyte red; GLuint sliceOffset = k ? imageOffsets[k] / 2 : 0; - unsigned_fetch_texel_rgtc(rowStride, map + sliceOffset, i, j, &red, 1); + signed_fetch_texel_rgtc(rowStride, (GLbyte *) map + sliceOffset, + i, j, &red, 1); texel[RCOMP] = texel[GCOMP] = texel[BCOMP] = BYTE_TO_FLOAT(red); diff --git a/mesalib/src/mesa/main/texcompress_s3tc.c b/mesalib/src/mesa/main/texcompress_s3tc.c index 23a5a0868..4a81ad803 100644 --- a/mesalib/src/mesa/main/texcompress_s3tc.c +++ b/mesalib/src/mesa/main/texcompress_s3tc.c @@ -417,6 +417,80 @@ fetch_rgba_dxt5(const GLubyte *map, const GLuint imageOffsets[], } +static void +fetch_srgb_dxt1(const GLubyte *map, const GLuint imageOffsets[], + GLint rowStride, GLint i, GLint j, GLint k, GLfloat *texel) +{ + if (fetch_ext_rgb_dxt1) { + GLuint sliceOffset = k ? imageOffsets[k] / 2 : 0; + GLubyte tex[4]; + fetch_ext_rgb_dxt1(rowStride, map + sliceOffset, i, j, tex); + texel[RCOMP] = _mesa_nonlinear_to_linear(tex[RCOMP]); + texel[GCOMP] = _mesa_nonlinear_to_linear(tex[GCOMP]); + texel[BCOMP] = _mesa_nonlinear_to_linear(tex[BCOMP]); + texel[ACOMP] = UBYTE_TO_FLOAT(tex[ACOMP]); + } + else { + problem("srgb_dxt1"); + } +} + +static void +fetch_srgba_dxt1(const GLubyte *map, const GLuint imageOffsets[], + GLint rowStride, GLint i, GLint j, GLint k, GLfloat *texel) +{ + if (fetch_ext_rgba_dxt1) { + GLuint sliceOffset = k ? imageOffsets[k] / 2 : 0; + GLubyte tex[4]; + fetch_ext_rgba_dxt1(rowStride, map + sliceOffset, i, j, tex); + texel[RCOMP] = _mesa_nonlinear_to_linear(tex[RCOMP]); + texel[GCOMP] = _mesa_nonlinear_to_linear(tex[GCOMP]); + texel[BCOMP] = _mesa_nonlinear_to_linear(tex[BCOMP]); + texel[ACOMP] = UBYTE_TO_FLOAT(tex[ACOMP]); + } + else { + problem("srgba_dxt1"); + } +} + +static void +fetch_srgba_dxt3(const GLubyte *map, const GLuint imageOffsets[], + GLint rowStride, GLint i, GLint j, GLint k, GLfloat *texel) +{ + if (fetch_ext_rgba_dxt3) { + GLuint sliceOffset = k ? imageOffsets[k] : 0; + GLubyte tex[4]; + fetch_ext_rgba_dxt3(rowStride, map + sliceOffset, i, j, tex); + texel[RCOMP] = _mesa_nonlinear_to_linear(tex[RCOMP]); + texel[GCOMP] = _mesa_nonlinear_to_linear(tex[GCOMP]); + texel[BCOMP] = _mesa_nonlinear_to_linear(tex[BCOMP]); + texel[ACOMP] = UBYTE_TO_FLOAT(tex[ACOMP]); + } + else { + problem("srgba_dxt3"); + } +} + +static void +fetch_srgba_dxt5(const GLubyte *map, const GLuint imageOffsets[], + GLint rowStride, GLint i, GLint j, GLint k, GLfloat *texel) +{ + if (fetch_ext_rgba_dxt5) { + GLuint sliceOffset = k ? imageOffsets[k] : 0; + GLubyte tex[4]; + fetch_ext_rgba_dxt5(rowStride, map + sliceOffset, i, j, tex); + texel[RCOMP] = _mesa_nonlinear_to_linear(tex[RCOMP]); + texel[GCOMP] = _mesa_nonlinear_to_linear(tex[GCOMP]); + texel[BCOMP] = _mesa_nonlinear_to_linear(tex[BCOMP]); + texel[ACOMP] = UBYTE_TO_FLOAT(tex[ACOMP]); + } + else { + problem("srgba_dxt5"); + } +} + + + compressed_fetch_func _mesa_get_dxt_fetch_func(gl_format format) { @@ -429,6 +503,14 @@ _mesa_get_dxt_fetch_func(gl_format format) return fetch_rgba_dxt3; case MESA_FORMAT_RGBA_DXT5: return fetch_rgba_dxt5; + case MESA_FORMAT_SRGB_DXT1: + return fetch_srgb_dxt1; + case MESA_FORMAT_SRGBA_DXT1: + return fetch_srgba_dxt1; + case MESA_FORMAT_SRGBA_DXT3: + return fetch_srgba_dxt3; + case MESA_FORMAT_SRGBA_DXT5: + return fetch_srgba_dxt5; default: return NULL; } diff --git a/mesalib/src/mesa/main/texgetimage.c b/mesalib/src/mesa/main/texgetimage.c index 69067df9f..d435c8269 100644 --- a/mesalib/src/mesa/main/texgetimage.c +++ b/mesalib/src/mesa/main/texgetimage.c @@ -683,6 +683,8 @@ legal_getteximage_target(struct gl_context *ctx, GLenum target) case GL_TEXTURE_2D_ARRAY_EXT: return (ctx->Extensions.MESA_texture_array || ctx->Extensions.EXT_texture_array); + case GL_TEXTURE_CUBE_MAP_ARRAY: + return ctx->Extensions.ARB_texture_cube_map_array; default: return GL_FALSE; } diff --git a/mesalib/src/mesa/main/teximage.c b/mesalib/src/mesa/main/teximage.c index 7a0d944fd..33f81a25c 100644 --- a/mesalib/src/mesa/main/teximage.c +++ b/mesalib/src/mesa/main/teximage.c @@ -3507,7 +3507,8 @@ compressed_subtexture_error_check(struct gl_context *ctx, GLint dims, GLint expectedSize; GLboolean targetOK; - if (dims == 2) { + switch (dims) { + case 2: switch (target) { case GL_TEXTURE_2D: case GL_TEXTURE_CUBE_MAP_POSITIVE_X: @@ -3520,12 +3521,17 @@ compressed_subtexture_error_check(struct gl_context *ctx, GLint dims, break; default: targetOK = GL_FALSE; + break; } - } - else { - assert(dims == 1 || dims == 3); - /* no 1D or 3D compressed textures at this time */ + break; + case 3: + targetOK = (target == GL_TEXTURE_2D_ARRAY); + break; + default: + assert(dims == 1); + /* no 1D compressed textures at this time */ targetOK = GL_FALSE; + break; } if (!targetOK) { diff --git a/mesalib/src/mesa/main/texstore.c b/mesalib/src/mesa/main/texstore.c index 26c5b6703..751150937 100644 --- a/mesalib/src/mesa/main/texstore.c +++ b/mesalib/src/mesa/main/texstore.c @@ -4441,9 +4441,9 @@ _mesa_store_compressed_teximage(struct gl_context *ctx, GLuint dims, struct gl_texture_image *texImage, GLsizei imageSize, const GLvoid *data) { - /* only 2D compressed images are supported at this time */ - if (dims != 2) { - _mesa_problem(ctx, "Unexpected glCompressedTexImage1D/3D call"); + /* only 2D and 3D compressed images are supported at this time */ + if (dims == 1) { + _mesa_problem(ctx, "Unexpected glCompressedTexImage1D call"); return; } @@ -4454,11 +4454,11 @@ _mesa_store_compressed_teximage(struct gl_context *ctx, GLuint dims, ASSERT(texImage); ASSERT(texImage->Width > 0); ASSERT(texImage->Height > 0); - ASSERT(texImage->Depth == 1); + ASSERT(texImage->Depth > 0); /* allocate storage for texture data */ if (!ctx->Driver.AllocTextureImageBuffer(ctx, texImage)) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D"); + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage%uD", dims); return; } @@ -4487,45 +4487,49 @@ _mesa_store_compressed_texsubimage(struct gl_context *ctx, GLuint dims, const GLubyte *src; const gl_format texFormat = texImage->TexFormat; GLuint bw, bh; + GLuint slice; - if (dims != 2) { - _mesa_problem(ctx, "Unexpected 1D/3D compressed texsubimage call"); + if (dims == 1) { + _mesa_problem(ctx, "Unexpected 1D compressed texsubimage call"); return; } _mesa_get_format_block_size(texFormat, &bw, &bh); /* get pointer to src pixels (may be in a pbo which we'll map here) */ - data = _mesa_validate_pbo_compressed_teximage(ctx, imageSize, data, + data = _mesa_validate_pbo_compressed_teximage(ctx, dims, imageSize, data, &ctx->Unpack, - "glCompressedTexSubImage2D"); + "glCompressedTexSubImage"); if (!data) return; srcRowStride = _mesa_format_row_stride(texFormat, width); src = (const GLubyte *) data; - /* Map dest texture buffer */ - ctx->Driver.MapTextureImage(ctx, texImage, 0, - xoffset, yoffset, width, height, - GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT, - &dstMap, &dstRowStride); + for (slice = 0; slice < depth; slice++) { + /* Map dest texture buffer */ + ctx->Driver.MapTextureImage(ctx, texImage, slice + zoffset, + xoffset, yoffset, width, height, + GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT, + &dstMap, &dstRowStride); - if (dstMap) { - bytesPerRow = srcRowStride; /* bytes per row of blocks */ - rows = (height + bh - 1) / bh; /* rows in blocks */ + if (dstMap) { + bytesPerRow = srcRowStride; /* bytes per row of blocks */ + rows = (height + bh - 1) / bh; /* rows in blocks */ - /* copy rows of blocks */ - for (i = 0; i < rows; i++) { - memcpy(dstMap, src, bytesPerRow); - dstMap += dstRowStride; - src += srcRowStride; - } + /* copy rows of blocks */ + for (i = 0; i < rows; i++) { + memcpy(dstMap, src, bytesPerRow); + dstMap += dstRowStride; + src += srcRowStride; + } - ctx->Driver.UnmapTextureImage(ctx, texImage, 0); - } - else { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexSubImage2D"); + ctx->Driver.UnmapTextureImage(ctx, texImage, slice + zoffset); + } + else { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexSubImage%uD", + dims); + } } _mesa_unmap_teximage_pbo(ctx, &ctx->Unpack); diff --git a/mesalib/src/mesa/main/transformfeedback.c b/mesalib/src/mesa/main/transformfeedback.c index 22060c34c..1bf4beaeb 100644 --- a/mesalib/src/mesa/main/transformfeedback.c +++ b/mesalib/src/mesa/main/transformfeedback.c @@ -34,6 +34,7 @@ #include "bufferobj.h" #include "context.h" #include "hash.h" +#include "macros.h" #include "mfeatures.h" #include "mtypes.h" #include "transformfeedback.h" @@ -79,6 +80,7 @@ reference_transform_feedback_object(struct gl_transform_feedback_object **ptr, } else { obj->RefCount++; + obj->EverBound = GL_TRUE; *ptr = obj; } } @@ -177,6 +179,7 @@ new_transform_feedback(struct gl_context *ctx, GLuint name) if (obj) { obj->Name = name; obj->RefCount = 1; + obj->EverBound = GL_FALSE; } return obj; } @@ -246,6 +249,83 @@ _mesa_init_transform_feedback_functions(struct dd_function_table *driver) /** + * Fill in the correct Size value for each buffer in \c obj. + * + * From the GL 4.3 spec, section 6.1.1 ("Binding Buffer Objects to Indexed + * Targets"): + * + * BindBufferBase binds the entire buffer, even when the size of the buffer + * is changed after the binding is established. It is equivalent to calling + * BindBufferRange with offset zero, while size is determined by the size of + * the bound buffer at the time the binding is used. + * + * Regardless of the size specified with BindBufferRange, or indirectly with + * BindBufferBase, the GL will never read or write beyond the end of a bound + * buffer. In some cases this constraint may result in visibly different + * behavior when a buffer overflow would otherwise result, such as described + * for transform feedback operations in section 13.2.2. + */ +static void +compute_transform_feedback_buffer_sizes( + struct gl_transform_feedback_object *obj) +{ + unsigned i = 0; + for (i = 0; i < MAX_FEEDBACK_BUFFERS; ++i) { + GLintptr offset = obj->Offset[i]; + GLsizeiptr buffer_size + = obj->Buffers[i] == NULL ? 0 : obj->Buffers[i]->Size; + GLsizeiptr available_space + = buffer_size <= offset ? 0 : buffer_size - offset; + GLsizeiptr computed_size; + if (obj->RequestedSize[i] == 0) { + /* No size was specified at the time the buffer was bound, so allow + * writing to all available space in the buffer. + */ + computed_size = available_space; + } else { + /* A size was specified at the time the buffer was bound, however + * it's possible that the buffer has shrunk since then. So only + * allow writing to the minimum of the specified size and the space + * available. + */ + computed_size = MIN2(available_space, obj->RequestedSize[i]); + } + + /* Legal sizes must be multiples of four, so round down if necessary. */ + obj->Size[i] = computed_size & ~0x3; + } +} + + +/** + * Compute the maximum number of vertices that can be written to the currently + * enabled transform feedback buffers without overflowing any of them. + */ +unsigned +_mesa_compute_max_transform_feedback_vertices( + const struct gl_transform_feedback_object *obj, + const struct gl_transform_feedback_info *info) +{ + unsigned max_index = 0xffffffff; + unsigned i; + + for (i = 0; i < info->NumBuffers; ++i) { + unsigned stride = info->BufferStride[i]; + unsigned max_for_this_buffer; + + /* Skip any inactive buffers, which have a stride of 0. */ + if (stride == 0) + continue; + + max_for_this_buffer = obj->Size[i] / (4 * stride); + max_index = MIN2(max_index, max_for_this_buffer); + } + + return max_index; +} + + +/** ** Begin API functions **/ @@ -256,6 +336,7 @@ _mesa_BeginTransformFeedback(GLenum mode) struct gl_transform_feedback_object *obj; struct gl_transform_feedback_info *info; GLuint i; + unsigned vertices_per_prim; GET_CURRENT_CONTEXT(ctx); obj = ctx->TransformFeedback.CurrentObject; @@ -276,9 +357,13 @@ _mesa_BeginTransformFeedback(GLenum mode) switch (mode) { case GL_POINTS: + vertices_per_prim = 1; + break; case GL_LINES: + vertices_per_prim = 2; + break; case GL_TRIANGLES: - /* legal */ + vertices_per_prim = 3; break; default: _mesa_error(ctx, GL_INVALID_ENUM, "glBeginTransformFeedback(mode)"); @@ -304,6 +389,20 @@ _mesa_BeginTransformFeedback(GLenum mode) obj->Active = GL_TRUE; ctx->TransformFeedback.Mode = mode; + compute_transform_feedback_buffer_sizes(obj); + + if (_mesa_is_gles3(ctx)) { + /* In GLES3, we are required to track the usage of the transform + * feedback buffer and report INVALID_OPERATION if a draw call tries to + * exceed it. So compute the maximum number of vertices that we can + * write without overflowing any of the buffers currently being used for + * feedback. + */ + unsigned max_vertices + = _mesa_compute_max_transform_feedback_vertices(obj, info); + obj->GlesRemainingPrims = max_vertices / vertices_per_prim; + } + assert(ctx->Driver.BeginTransformFeedback); ctx->Driver.BeginTransformFeedback(ctx, mode, obj); } @@ -362,7 +461,7 @@ bind_buffer_range(struct gl_context *ctx, GLuint index, obj->BufferNames[index] = bufObj->Name; obj->Offset[index] = offset; - obj->Size[index] = size; + obj->RequestedSize[index] = size; } @@ -421,7 +520,6 @@ _mesa_bind_buffer_base_transform_feedback(struct gl_context *ctx, struct gl_buffer_object *bufObj) { struct gl_transform_feedback_object *obj; - GLsizeiptr size; obj = ctx->TransformFeedback.CurrentObject; @@ -436,12 +534,7 @@ _mesa_bind_buffer_base_transform_feedback(struct gl_context *ctx, return; } - /* default size is the buffer size rounded down to nearest - * multiple of four. - */ - size = bufObj->Size & ~0x3; - - bind_buffer_range(ctx, index, bufObj, 0, size); + bind_buffer_range(ctx, index, bufObj, 0, 0); } @@ -457,7 +550,6 @@ _mesa_BindBufferOffsetEXT(GLenum target, GLuint index, GLuint buffer, struct gl_transform_feedback_object *obj; struct gl_buffer_object *bufObj; GET_CURRENT_CONTEXT(ctx); - GLsizeiptr size; if (target != GL_TRANSFORM_FEEDBACK_BUFFER) { _mesa_error(ctx, GL_INVALID_ENUM, "glBindBufferOffsetEXT(target)"); @@ -497,12 +589,7 @@ _mesa_BindBufferOffsetEXT(GLenum target, GLuint index, GLuint buffer, return; } - /* default size is the buffer size rounded down to nearest - * multiple of four. - */ - size = (bufObj->Size - offset) & ~0x3; - - bind_buffer_range(ctx, index, bufObj, offset, size); + bind_buffer_range(ctx, index, bufObj, offset, 0); } @@ -708,14 +795,19 @@ _mesa_GenTransformFeedbacks(GLsizei n, GLuint *names) GLboolean GLAPIENTRY _mesa_IsTransformFeedback(GLuint name) { + struct gl_transform_feedback_object *obj; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); - if (name && _mesa_lookup_transform_feedback_object(ctx, name)) - return GL_TRUE; - else + if (name == 0) return GL_FALSE; + + obj = _mesa_lookup_transform_feedback_object(ctx, name); + if (obj == NULL) + return GL_FALSE; + + return obj->EverBound; } @@ -734,8 +826,7 @@ _mesa_BindTransformFeedback(GLenum target, GLuint name) return; } - if (ctx->TransformFeedback.CurrentObject->Active && - !ctx->TransformFeedback.CurrentObject->Paused) { + if (_mesa_is_xfb_active_and_unpaused(ctx)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glBindTransformFeedback(transform is active, or not paused)"); return; @@ -805,7 +896,7 @@ _mesa_PauseTransformFeedback(void) obj = ctx->TransformFeedback.CurrentObject; - if (!obj->Active || obj->Paused) { + if (!_mesa_is_xfb_active_and_unpaused(ctx)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glPauseTransformFeedback(feedback not active or already paused)"); return; diff --git a/mesalib/src/mesa/main/transformfeedback.h b/mesalib/src/mesa/main/transformfeedback.h index 01c2af359..c128746b3 100644 --- a/mesalib/src/mesa/main/transformfeedback.h +++ b/mesalib/src/mesa/main/transformfeedback.h @@ -25,9 +25,11 @@ #ifndef TRANSFORM_FEEDBACK_H #define TRANSFORM_FEEDBACK_H +#include <stdbool.h> #include "compiler.h" #include "glheader.h" #include "mfeatures.h" +#include "mtypes.h" struct _glapi_table; struct dd_function_table; @@ -46,6 +48,11 @@ _mesa_validate_transform_feedback_buffers(struct gl_context *ctx); extern void _mesa_init_transform_feedback_functions(struct dd_function_table *driver); +extern unsigned +_mesa_compute_max_transform_feedback_vertices( + const struct gl_transform_feedback_object *obj, + const struct gl_transform_feedback_info *info); + /*** GL_EXT_transform_feedback ***/ @@ -106,4 +113,11 @@ _mesa_PauseTransformFeedback(void); extern void GLAPIENTRY _mesa_ResumeTransformFeedback(void); +static inline bool +_mesa_is_xfb_active_and_unpaused(const struct gl_context *ctx) +{ + return ctx->TransformFeedback.CurrentObject->Active && + !ctx->TransformFeedback.CurrentObject->Paused; +} + #endif /* TRANSFORM_FEEDBACK_H */ diff --git a/mesalib/src/mesa/main/uniform_query.cpp b/mesalib/src/mesa/main/uniform_query.cpp index b6b73d16f..afe9a08c1 100644 --- a/mesalib/src/mesa/main/uniform_query.cpp +++ b/mesalib/src/mesa/main/uniform_query.cpp @@ -241,11 +241,14 @@ validate_uniform_parameters(struct gl_context *ctx, return false; } - /* This case should be impossible. The implication is that a call like - * glGetUniformLocation(prog, "foo[8]") was successful but "foo" is not an - * array. + /* If the uniform is an array, check that array_index is in bounds. + * If not an array, check that array_index is zero. + * array_index is unsigned so no need to check for less than zero. */ - if (*array_index != 0 && shProg->UniformStorage[*loc].array_elements == 0) { + unsigned limit = shProg->UniformStorage[*loc].array_elements; + if (limit == 0) + limit = 1; + if (*array_index >= limit) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(location=%d)", caller, location); return false; @@ -732,9 +735,6 @@ _mesa_uniform(struct gl_context *ctx, struct gl_shader_program *shProg, * will have already generated an error. */ if (uni->array_elements != 0) { - if (offset >= uni->array_elements) - return; - count = MIN2(count, (int) (uni->array_elements - offset)); } @@ -889,9 +889,6 @@ _mesa_uniform_matrix(struct gl_context *ctx, struct gl_shader_program *shProg, * will have already generated an error. */ if (uni->array_elements != 0) { - if (offset >= uni->array_elements) - return; - count = MIN2(count, (int) (uni->array_elements - offset)); } @@ -1025,10 +1022,13 @@ _mesa_get_uniform_location(struct gl_context *ctx, if (!found) return GL_INVALID_INDEX; - /* Since array_elements is 0 for non-arrays, this causes look-ups of 'a[0]' - * to (correctly) fail if 'a' is not an array. + /* If the uniform is an array, fail if the index is out of bounds. + * (A negative index is caught above.) This also fails if the uniform + * is not an array, but the user is trying to index it, because + * array_elements is zero and offset >= 0. */ - if (array_lookup && shProg->UniformStorage[location].array_elements == 0) { + if (array_lookup + && offset >= (long) shProg->UniformStorage[location].array_elements) { return GL_INVALID_INDEX; } diff --git a/mesalib/src/mesa/state_tracker/st_atom_array.c b/mesalib/src/mesa/state_tracker/st_atom_array.c index 15f5d1c95..2437245bd 100644 --- a/mesalib/src/mesa/state_tracker/st_atom_array.c +++ b/mesalib/src/mesa/state_tracker/st_atom_array.c @@ -403,9 +403,9 @@ setup_interleaved_attribs(const struct st_vertex_program *vp, const GLuint mesaAttr = vp->index_to_input[attr]; const struct gl_client_array *array = arrays[mesaAttr]; unsigned src_offset = (unsigned) (array->Ptr - low_addr); - GLuint element_size = array->_ElementSize; - assert(element_size == array->Size * _mesa_sizeof_type(array->Type)); + assert(array->_ElementSize == + _mesa_bytes_per_vertex_attrib(array->Size, array->Type)); velements[attr].src_offset = src_offset; velements[attr].instance_divisor = array->InstanceDivisor; @@ -474,7 +474,8 @@ setup_non_interleaved_attribs(struct st_context *st, struct gl_buffer_object *bufobj = array->BufferObj; GLsizei stride = array->StrideB; - assert(array->_ElementSize == array->Size * _mesa_sizeof_type(array->Type)); + assert(array->_ElementSize == + _mesa_bytes_per_vertex_attrib(array->Size, array->Type)); if (_mesa_is_bufferobj(bufobj)) { /* Attribute data is in a VBO. diff --git a/mesalib/src/mesa/state_tracker/st_cb_flush.c b/mesalib/src/mesa/state_tracker/st_cb_flush.c index 7c9f91f1b..b569e3b3c 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_flush.c +++ b/mesalib/src/mesa/state_tracker/st_cb_flush.c @@ -76,15 +76,16 @@ display_front_buffer(struct st_context *st) } -void st_flush( struct st_context *st, - struct pipe_fence_handle **fence ) +void st_flush(struct st_context *st, + struct pipe_fence_handle **fence, + enum pipe_flush_flags flags) { FLUSH_VERTICES(st->ctx, 0); FLUSH_CURRENT(st->ctx, 0); st_flush_bitmap_cache(st); - st->pipe->flush( st->pipe, fence ); + st->pipe->flush(st->pipe, fence, flags); } @@ -95,7 +96,7 @@ void st_finish( struct st_context *st ) { struct pipe_fence_handle *fence = NULL; - st_flush(st, &fence); + st_flush(st, &fence, 0); if(fence) { st->pipe->screen->fence_finish(st->pipe->screen, fence, @@ -118,7 +119,7 @@ static void st_glFlush(struct gl_context *ctx) * synchronization issues. Calling finish() here will just hide * problems that need to be fixed elsewhere. */ - st_flush(st, NULL); + st_flush(st, NULL, 0); if (is_front_buffer_dirty(st)) { display_front_buffer(st); diff --git a/mesalib/src/mesa/state_tracker/st_cb_flush.h b/mesalib/src/mesa/state_tracker/st_cb_flush.h index 598536ba0..003e2a2a9 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_flush.h +++ b/mesalib/src/mesa/state_tracker/st_cb_flush.h @@ -41,7 +41,8 @@ st_init_flush_functions(struct dd_function_table *functions); extern void st_flush(struct st_context *st, - struct pipe_fence_handle **fence); + struct pipe_fence_handle **fence, + enum pipe_flush_flags flags); extern void st_finish(struct st_context *st); diff --git a/mesalib/src/mesa/state_tracker/st_cb_queryobj.c b/mesalib/src/mesa/state_tracker/st_cb_queryobj.c index b10fd9335..98b61f576 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_queryobj.c +++ b/mesalib/src/mesa/state_tracker/st_cb_queryobj.c @@ -72,6 +72,11 @@ st_DeleteQuery(struct gl_context *ctx, struct gl_query_object *q) stq->pq = NULL; } + if (stq->pq_begin) { + pipe->destroy_query(pipe, stq->pq_begin); + stq->pq_begin = NULL; + } + free(stq); } @@ -79,7 +84,8 @@ st_DeleteQuery(struct gl_context *ctx, struct gl_query_object *q) static void st_BeginQuery(struct gl_context *ctx, struct gl_query_object *q) { - struct pipe_context *pipe = st_context(ctx)->pipe; + struct st_context *st = st_context(ctx); + struct pipe_context *pipe = st->pipe; struct st_query_object *stq = st_query_object(q); unsigned type; @@ -98,29 +104,46 @@ st_BeginQuery(struct gl_context *ctx, struct gl_query_object *q) case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: type = PIPE_QUERY_PRIMITIVES_EMITTED; break; - case GL_TIME_ELAPSED_EXT: - type = PIPE_QUERY_TIME_ELAPSED; + case GL_TIME_ELAPSED: + if (st->has_time_elapsed) + type = PIPE_QUERY_TIME_ELAPSED; + else + type = PIPE_QUERY_TIMESTAMP; break; default: assert(0 && "unexpected query target in st_BeginQuery()"); return; } - if (stq->pq && stq->type != type) { + if (stq->type != type) { /* free old query of different type */ - pipe->destroy_query(pipe, stq->pq); - stq->pq = NULL; + if (stq->pq) { + pipe->destroy_query(pipe, stq->pq); + stq->pq = NULL; + } + if (stq->pq_begin) { + pipe->destroy_query(pipe, stq->pq_begin); + stq->pq_begin = NULL; + } stq->type = PIPE_QUERY_TYPES; /* an invalid value */ } - if (!stq->pq) { - stq->pq = pipe->create_query(pipe, type); - stq->type = type; + if (q->Target == GL_TIME_ELAPSED && + type == PIPE_QUERY_TIMESTAMP) { + /* Determine time elapsed by emitting two timestamp queries. */ + if (!stq->pq_begin) { + stq->pq_begin = pipe->create_query(pipe, type); + stq->type = type; + } + pipe->end_query(pipe, stq->pq_begin); + } else { + if (!stq->pq) { + stq->pq = pipe->create_query(pipe, type); + stq->type = type; + } + pipe->begin_query(pipe, stq->pq); } - assert(stq->type == type); - - pipe->begin_query(pipe, stq->pq); } @@ -132,7 +155,9 @@ st_EndQuery(struct gl_context *ctx, struct gl_query_object *q) st_flush_bitmap_cache(st_context(ctx)); - if (q->Target == GL_TIMESTAMP && !stq->pq) { + if ((q->Target == GL_TIMESTAMP || + q->Target == GL_TIME_ELAPSED) && + !stq->pq) { stq->pq = pipe->create_query(pipe, PIPE_QUERY_TIMESTAMP); stq->type = PIPE_QUERY_TIMESTAMP; } @@ -141,6 +166,33 @@ st_EndQuery(struct gl_context *ctx, struct gl_query_object *q) } +static boolean +get_query_result(struct pipe_context *pipe, + struct st_query_object *stq, + boolean wait) +{ + if (!pipe->get_query_result(pipe, + stq->pq, + wait, + (void *)&stq->base.Result)) { + return FALSE; + } + + if (stq->base.Target == GL_TIME_ELAPSED && + stq->type == PIPE_QUERY_TIMESTAMP) { + /* Calculate the elapsed time from the two timestamp queries */ + GLuint64EXT Result0 = 0; + assert(stq->pq_begin); + pipe->get_query_result(pipe, stq->pq_begin, TRUE, (void *)&Result0); + stq->base.Result -= Result0; + } else { + assert(!stq->pq_begin); + } + + return TRUE; +} + + static void st_WaitQuery(struct gl_context *ctx, struct gl_query_object *q) { @@ -151,10 +203,7 @@ st_WaitQuery(struct gl_context *ctx, struct gl_query_object *q) assert(!stq->base.Ready); while (!stq->base.Ready && - !pipe->get_query_result(pipe, - stq->pq, - TRUE, - (void*)&q->Result)) + !get_query_result(pipe, stq, TRUE)) { /* nothing */ } @@ -169,7 +218,7 @@ st_CheckQuery(struct gl_context *ctx, struct gl_query_object *q) struct pipe_context *pipe = st_context(ctx)->pipe; struct st_query_object *stq = st_query_object(q); assert(!q->Ready); /* we should not get called if Ready is TRUE */ - q->Ready = pipe->get_query_result(pipe, stq->pq, FALSE, (void*)&q->Result); + q->Ready = get_query_result(pipe, stq, FALSE); } diff --git a/mesalib/src/mesa/state_tracker/st_cb_queryobj.h b/mesalib/src/mesa/state_tracker/st_cb_queryobj.h index 03487b153..d5b107532 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_queryobj.h +++ b/mesalib/src/mesa/state_tracker/st_cb_queryobj.h @@ -39,6 +39,10 @@ struct st_query_object { struct gl_query_object base; struct pipe_query *pq; + + /* Begin TIMESTAMP query for GL_TIME_ELAPSED_EXT queries */ + struct pipe_query *pq_begin; + unsigned type; /**< PIPE_QUERY_x */ }; diff --git a/mesalib/src/mesa/state_tracker/st_cb_syncobj.c b/mesalib/src/mesa/state_tracker/st_cb_syncobj.c index f9f2348a3..94bf4861d 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_syncobj.c +++ b/mesalib/src/mesa/state_tracker/st_cb_syncobj.c @@ -72,7 +72,7 @@ static void st_fence_sync(struct gl_context *ctx, struct gl_sync_object *obj, assert(condition == GL_SYNC_GPU_COMMANDS_COMPLETE && flags == 0); assert(so->fence == NULL); - pipe->flush(pipe, &so->fence); + pipe->flush(pipe, &so->fence, 0); } static void st_check_sync(struct gl_context *ctx, struct gl_sync_object *obj) diff --git a/mesalib/src/mesa/state_tracker/st_cb_texture.c b/mesalib/src/mesa/state_tracker/st_cb_texture.c index bf13526d2..02fc675ae 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_texture.c +++ b/mesalib/src/mesa/state_tracker/st_cb_texture.c @@ -201,7 +201,7 @@ st_MapTextureImage(struct gl_context *ctx, if (mode & GL_MAP_INVALIDATE_RANGE_BIT) pipeMode |= PIPE_TRANSFER_DISCARD_RANGE; - map = st_texture_image_map(st, stImage, slice, pipeMode, x, y, w, h); + map = st_texture_image_map(st, stImage, pipeMode, x, y, slice, w, h, 1); if (map) { *mapOut = map; *rowStrideOut = stImage->transfer->stride; @@ -572,37 +572,68 @@ decompress_with_blit(struct gl_context * ctx, { struct st_context *st = st_context(ctx); struct pipe_context *pipe = st->pipe; - struct st_texture_image *stImage = st_texture_image(texImage); - struct st_texture_object *stObj = st_texture_object(texImage->TexObject); + struct pipe_screen *screen = pipe->screen; const GLuint width = texImage->Width; const GLuint height = texImage->Height; - struct pipe_resource *dst_texture; + const GLuint depth = texImage->Depth; + struct pipe_resource *src = st_texture_object(texImage->TexObject)->pt; + struct pipe_resource *dst; + struct pipe_resource dst_templ; + enum pipe_format pipe_format; + gl_format mesa_format; + GLenum gl_target = texImage->TexObject->Target; + enum pipe_texture_target pipe_target; struct pipe_blit_info blit; unsigned bind = (PIPE_BIND_RENDER_TARGET | PIPE_BIND_TRANSFER_READ); struct pipe_transfer *tex_xfer; ubyte *map; - /* create temp / dest surface */ - if (!util_create_rgba_texture(pipe, width, height, bind, - &dst_texture)) { - _mesa_problem(ctx, "util_create_rgba_texture() failed " - "in decompress_with_blit()"); + /* GetTexImage only returns a single face for cubemaps. */ + if (gl_target == GL_TEXTURE_CUBE_MAP) { + gl_target = GL_TEXTURE_2D; + } + + pipe_target = gl_target_to_pipe(gl_target); + + /* Find the best match for the format+type combo. */ + pipe_format = st_choose_format(pipe->screen, GL_RGBA8, format, type, + pipe_target, 0, bind); + if (pipe_format == PIPE_FORMAT_NONE) { + /* unable to get an rgba format!?! */ + _mesa_problem(ctx, "%s: cannot find a supported format", __func__); return; } - blit.src.resource = stObj->pt; + /* create the destination texture */ + memset(&dst_templ, 0, sizeof(dst_templ)); + dst_templ.target = pipe_target; + dst_templ.format = pipe_format; + dst_templ.bind = bind; + dst_templ.usage = PIPE_USAGE_STAGING; + + st_gl_texture_dims_to_pipe_dims(gl_target, width, height, depth, + &dst_templ.width0, &dst_templ.height0, + &dst_templ.depth0, &dst_templ.array_size); + + dst = screen->resource_create(screen, &dst_templ); + if (!dst) { + _mesa_problem(ctx, "%s: cannot create a temporary texture", __func__); + return; + } + + blit.src.resource = src; blit.src.level = texImage->Level; - blit.src.format = util_format_linear(stObj->pt->format); - blit.dst.resource = dst_texture; + blit.src.format = util_format_linear(src->format); + blit.dst.resource = dst; blit.dst.level = 0; - blit.dst.format = dst_texture->format; + blit.dst.format = dst->format; blit.src.box.x = blit.dst.box.x = 0; blit.src.box.y = blit.dst.box.y = 0; - blit.src.box.z = 0; /* XXX compressed array textures? */ + blit.src.box.z = texImage->Face; blit.dst.box.z = 0; blit.src.box.width = blit.dst.box.width = width; blit.src.box.height = blit.dst.box.height = height; - blit.src.box.depth = blit.dst.box.depth = 1; + blit.src.box.depth = blit.dst.box.depth = depth; blit.mask = PIPE_MASK_RGBA; blit.filter = PIPE_TEX_FILTER_NEAREST; blit.scissor_enable = FALSE; @@ -612,33 +643,38 @@ decompress_with_blit(struct gl_context * ctx, pixels = _mesa_map_pbo_dest(ctx, &ctx->Pack, pixels); - map = pipe_transfer_map(pipe, dst_texture, 0, 0, - PIPE_TRANSFER_READ, - 0, 0, width, height, &tex_xfer); + map = pipe_transfer_map_3d(pipe, dst, 0, PIPE_TRANSFER_READ, + 0, 0, 0, width, height, depth, &tex_xfer); if (!map) { goto end; } + mesa_format = st_pipe_format_to_mesa_format(pipe_format); + /* copy/pack data into user buffer */ - if (_mesa_format_matches_format_and_type(stImage->base.TexFormat, - format, type, + if (_mesa_format_matches_format_and_type(mesa_format, format, type, ctx->Pack.SwapBytes)) { /* memcpy */ - const uint bytesPerRow = width * util_format_get_blocksize(stImage->pt->format); - /* map the dst_surface so we can read from it */ - GLuint row; - for (row = 0; row < height; row++) { - GLvoid *dest = _mesa_image_address2d(&ctx->Pack, pixels, width, - height, format, type, row, 0); - memcpy(dest, map, bytesPerRow); - map += tex_xfer->stride; + const uint bytesPerRow = width * util_format_get_blocksize(pipe_format); + GLuint row, slice; + + for (slice = 0; slice < depth; slice++) { + ubyte *slice_map = map; + + for (row = 0; row < height; row++) { + GLvoid *dest = _mesa_image_address3d(&ctx->Pack, pixels, + width, height, format, + type, slice, row, 0); + memcpy(dest, slice_map, bytesPerRow); + slice_map += tex_xfer->stride; + } + map += tex_xfer->layer_stride; } - pipe_transfer_unmap(pipe, tex_xfer); } else { /* format translation via floats */ - GLuint row; - enum pipe_format pformat = util_format_linear(dst_texture->format); + GLuint row, slice; + enum pipe_format pformat = util_format_linear(dst->format); GLfloat *rgba; rgba = malloc(width * 4 * sizeof(GLfloat)); @@ -647,20 +683,24 @@ decompress_with_blit(struct gl_context * ctx, goto end; } - for (row = 0; row < height; row++) { - const GLbitfield transferOps = 0x0; /* bypassed for glGetTexImage() */ - GLvoid *dest = _mesa_image_address2d(&ctx->Pack, pixels, width, - height, format, type, row, 0); + for (slice = 0; slice < depth; slice++) { + for (row = 0; row < height; row++) { + const GLbitfield transferOps = 0x0; /* bypassed for glGetTexImage() */ + GLvoid *dest = _mesa_image_address3d(&ctx->Pack, pixels, + width, height, format, + type, slice, row, 0); - if (ST_DEBUG & DEBUG_FALLBACK) - debug_printf("%s: fallback format translation\n", __FUNCTION__); + if (ST_DEBUG & DEBUG_FALLBACK) + debug_printf("%s: fallback format translation\n", __FUNCTION__); - /* get float[4] rgba row from surface */ - pipe_get_tile_rgba_format(tex_xfer, map, 0, row, width, 1, - pformat, rgba); + /* get float[4] rgba row from surface */ + pipe_get_tile_rgba_format(tex_xfer, map, 0, row, width, 1, + pformat, rgba); - _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba, format, - type, dest, &ctx->Pack, transferOps); + _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba, format, + type, dest, &ctx->Pack, transferOps); + } + map += tex_xfer->layer_stride; } free(rgba); @@ -671,7 +711,7 @@ end: pipe_transfer_unmap(pipe, tex_xfer); _mesa_unmap_pbo_dest(ctx, &ctx->Pack); - pipe_resource_reference(&dst_texture, NULL); + pipe_resource_reference(&dst, NULL); } @@ -722,6 +762,9 @@ fallback_copy_texsubimage(struct gl_context *ctx, GLvoid *texDest; enum pipe_transfer_usage transfer_usage; void *map; + unsigned dst_width = width; + unsigned dst_height = height; + unsigned dst_depth = 1; if (ST_DEBUG & DEBUG_FALLBACK) debug_printf("%s: fallback processing\n", __FUNCTION__); @@ -730,6 +773,14 @@ fallback_copy_texsubimage(struct gl_context *ctx, srcY = strb->Base.Height - srcY - height; } + if (stImage->pt->target == PIPE_TEXTURE_1D_ARRAY) { + /* Move y/height to z/depth for 1D array textures. */ + destZ = destY; + destY = 0; + dst_depth = dst_height; + dst_height = 1; + } + map = pipe_transfer_map(pipe, strb->texture, strb->rtt_level, @@ -745,9 +796,9 @@ fallback_copy_texsubimage(struct gl_context *ctx, else transfer_usage = PIPE_TRANSFER_WRITE; - /* XXX this used to ignore destZ param */ - texDest = st_texture_image_map(st, stImage, destZ, transfer_usage, - destX, destY, width, height); + texDest = st_texture_image_map(st, stImage, transfer_usage, + destX, destY, destZ, + dst_width, dst_height, dst_depth); if (baseFormat == GL_DEPTH_COMPONENT || baseFormat == GL_DEPTH_STENCIL) { @@ -775,8 +826,16 @@ fallback_copy_texsubimage(struct gl_context *ctx, if (scaleOrBias) { _mesa_scale_and_bias_depth_uint(ctx, width, data); } - pipe_put_tile_z(stImage->transfer, texDest, 0, row, width, 1, - data); + + if (stImage->pt->target == PIPE_TEXTURE_1D_ARRAY) { + pipe_put_tile_z(stImage->transfer, + texDest + row*stImage->transfer->layer_stride, + 0, 0, width, 1, data); + } + else { + pipe_put_tile_z(stImage->transfer, texDest, 0, row, width, 1, + data); + } } } else { @@ -792,7 +851,7 @@ fallback_copy_texsubimage(struct gl_context *ctx, if (tempSrc && texDest) { const GLint dims = 2; - const GLint dstRowStride = stImage->transfer->stride; + GLint dstRowStride; struct gl_texture_image *texImage = &stImage->base; struct gl_pixelstore_attrib unpack = ctx->DefaultPacking; @@ -800,6 +859,13 @@ fallback_copy_texsubimage(struct gl_context *ctx, unpack.Invert = GL_TRUE; } + if (stImage->pt->target == PIPE_TEXTURE_1D_ARRAY) { + dstRowStride = stImage->transfer->layer_stride; + } + else { + dstRowStride = stImage->transfer->stride; + } + /* get float/RGBA image from framebuffer */ /* XXX this usually involves a lot of int/float conversion. * try to avoid that someday. @@ -901,6 +967,43 @@ compatible_src_dst_formats(struct gl_context *ctx, } +/** + * Do pipe->blit. Return FALSE if the blitting is unsupported + * for the given formats. + */ +static GLboolean +st_pipe_blit(struct pipe_context *pipe, struct pipe_blit_info *blit) +{ + struct pipe_screen *screen = pipe->screen; + unsigned dst_usage; + + if (util_format_is_depth_or_stencil(blit->dst.format)) { + dst_usage = PIPE_BIND_DEPTH_STENCIL; + } + else { + dst_usage = PIPE_BIND_RENDER_TARGET; + } + + /* try resource_copy_region in case the format is not supported + * for rendering */ + if (util_try_blit_via_copy_region(pipe, blit)) { + return GL_TRUE; /* done */ + } + + /* check the format support */ + if (!screen->is_format_supported(screen, blit->src.format, + PIPE_TEXTURE_2D, 0, + PIPE_BIND_SAMPLER_VIEW) || + !screen->is_format_supported(screen, blit->dst.format, + PIPE_TEXTURE_2D, 0, + dst_usage)) { + return GL_FALSE; + } + + pipe->blit(pipe, blit); + return GL_TRUE; +} + /** * Do a CopyTex[Sub]Image1/2/3D() using a hardware (blit) path if possible. @@ -929,7 +1032,7 @@ st_CopyTexSubImage(struct gl_context *ctx, GLuint dims, struct pipe_surface surf_tmpl; unsigned dst_usage; unsigned blit_mask; - GLint srcY0, srcY1; + GLint srcY0, srcY1, yStep; /* make sure finalize_textures has been called? */ @@ -950,10 +1053,12 @@ st_CopyTexSubImage(struct gl_context *ctx, GLuint dims, if (do_flip) { srcY1 = strb->Base.Height - srcY - height; srcY0 = srcY1 + height; + yStep = -1; } else { srcY0 = srcY; srcY1 = srcY0 + height; + yStep = 1; } if (ctx->_ImageTransferState) { @@ -965,16 +1070,6 @@ st_CopyTexSubImage(struct gl_context *ctx, GLuint dims, goto fallback; } - if (texImage->TexObject->Target == GL_TEXTURE_1D_ARRAY) { - /* 1D arrays might be thought of as 2D images but the actual layout - * might not be that way. At some points, we convert OpenGL's 1D - * array 'height' into gallium 'layers' and that prevents the blit - * utility code from doing the right thing. Simpy use the memcpy-based - * fallback. - */ - goto fallback; - } - /* Set the blit writemask. */ switch (texBaseFormat) { case GL_DEPTH_STENCIL: @@ -1055,27 +1150,38 @@ st_CopyTexSubImage(struct gl_context *ctx, GLuint dims, blit.mask = blit_mask; blit.filter = PIPE_TEX_FILTER_NEAREST; - /* try resource_copy_region in case the format is not supported - * for rendering */ - if (util_try_blit_via_copy_region(pipe, &blit)) { - return; /* done */ - } + /* 1D array textures need special treatment. + * Blit rows from the source to layers in the destination. */ + if (texImage->TexObject->Target == GL_TEXTURE_1D_ARRAY) { + int y, layer; - /* check the format support */ - if (!screen->is_format_supported(screen, src_format, - PIPE_TEXTURE_2D, 0, - PIPE_BIND_SAMPLER_VIEW) || - !screen->is_format_supported(screen, dest_format, - PIPE_TEXTURE_2D, 0, - dst_usage)) { - goto fallback; - } + for (y = srcY0, layer = 0; layer < height; y += yStep, layer++) { + blit.src.box.y = y; + blit.src.box.height = 1; + blit.dst.box.y = 0; + blit.dst.box.height = 1; + blit.dst.box.z = destY + layer; - pipe->blit(pipe, &blit); + if (!st_pipe_blit(pipe, &blit)) { + goto fallback; + } + } + } + else { + /* All the other texture targets. */ + if (!st_pipe_blit(pipe, &blit)) { + goto fallback; + } + } return; } /* try u_blit */ + if (texImage->TexObject->Target == GL_TEXTURE_1D_ARRAY) { + /* u_blit cannot copy 1D array textures as required by CopyTexSubImage */ + goto fallback; + } + color_writemask = compatible_src_dst_formats(ctx, &strb->Base, texImage); if (!color_writemask || diff --git a/mesalib/src/mesa/state_tracker/st_context.h b/mesalib/src/mesa/state_tracker/st_context.h index eeb7f0c4f..2be74b452 100644 --- a/mesalib/src/mesa/state_tracker/st_context.h +++ b/mesalib/src/mesa/state_tracker/st_context.h @@ -83,6 +83,7 @@ struct st_context GLboolean clamp_frag_color_in_shader; GLboolean clamp_vert_color_in_shader; boolean has_stencil_export; /**< can do shader stencil export? */ + boolean has_time_elapsed; /* On old libGL's for linux we need to invalidate the drawables * on glViewpport calls, this is set via a option. diff --git a/mesalib/src/mesa/state_tracker/st_extensions.c b/mesalib/src/mesa/state_tracker/st_extensions.c index 262cc3d6c..e7cf4f3bb 100644 --- a/mesalib/src/mesa/state_tracker/st_extensions.c +++ b/mesalib/src/mesa/state_tracker/st_extensions.c @@ -371,6 +371,7 @@ void st_init_extensions(struct st_context *st) { o(ARB_shader_texture_lod), PIPE_CAP_SM3 }, { o(ARB_shadow), PIPE_CAP_TEXTURE_SHADOW_MAP }, { o(ARB_texture_non_power_of_two), PIPE_CAP_NPOT_TEXTURES }, + { o(ARB_timer_query), PIPE_CAP_QUERY_TIMESTAMP }, { o(ARB_transform_feedback2), PIPE_CAP_STREAM_OUTPUT_PAUSE_RESUME }, { o(ARB_transform_feedback3), PIPE_CAP_STREAM_OUTPUT_PAUSE_RESUME }, @@ -382,7 +383,6 @@ void st_init_extensions(struct st_context *st) { o(EXT_texture_filter_anisotropic), PIPE_CAP_ANISOTROPIC_FILTER }, { o(EXT_texture_mirror_clamp), PIPE_CAP_TEXTURE_MIRROR_CLAMP }, { o(EXT_texture_swizzle), PIPE_CAP_TEXTURE_SWIZZLE }, - { o(EXT_timer_query), PIPE_CAP_TIMER_QUERY }, { o(EXT_transform_feedback), PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS }, { o(AMD_seamless_cubemap_per_texture), PIPE_CAP_SEAMLESS_CUBE_MAP_PER_TEXTURE }, @@ -652,9 +652,12 @@ void st_init_extensions(struct st_context *st) if (ctx->Const.MaxDualSourceDrawBuffers > 0) ctx->Extensions.ARB_blend_func_extended = GL_TRUE; - if (screen->get_param(screen, PIPE_CAP_TIMER_QUERY) && - screen->get_param(screen, PIPE_CAP_QUERY_TIMESTAMP)) { - ctx->Extensions.ARB_timer_query = GL_TRUE; + st->has_time_elapsed = + screen->get_param(screen, PIPE_CAP_QUERY_TIME_ELAPSED); + + if (st->has_time_elapsed || + ctx->Extensions.ARB_timer_query) { + ctx->Extensions.EXT_timer_query = GL_TRUE; } if (ctx->Extensions.ARB_transform_feedback2 && diff --git a/mesalib/src/mesa/state_tracker/st_manager.c b/mesalib/src/mesa/state_tracker/st_manager.c index 30f5ca5ed..a3a67712a 100644 --- a/mesalib/src/mesa/state_tracker/st_manager.c +++ b/mesalib/src/mesa/state_tracker/st_manager.c @@ -455,7 +455,13 @@ st_context_flush(struct st_context_iface *stctxi, unsigned flags, struct pipe_fence_handle **fence) { struct st_context *st = (struct st_context *) stctxi; - st_flush(st, fence); + enum pipe_flush_flags pipe_flags = 0; + + if (flags & ST_FLUSH_END_OF_FRAME) { + pipe_flags |= PIPE_FLUSH_END_OF_FRAME; + } + + st_flush(st, fence, pipe_flags); if (flags & ST_FLUSH_FRONT) st_manager_flush_frontbuffer(st); } diff --git a/mesalib/src/mesa/state_tracker/st_texture.c b/mesalib/src/mesa/state_tracker/st_texture.c index 5a4dcaab2..ee4d7622d 100644 --- a/mesalib/src/mesa/state_tracker/st_texture.c +++ b/mesalib/src/mesa/state_tracker/st_texture.c @@ -232,8 +232,9 @@ st_texture_match_image(const struct pipe_resource *pt, */ GLubyte * st_texture_image_map(struct st_context *st, struct st_texture_image *stImage, - GLuint zoffset, enum pipe_transfer_usage usage, - GLuint x, GLuint y, GLuint w, GLuint h) + enum pipe_transfer_usage usage, + GLuint x, GLuint y, GLuint z, + GLuint w, GLuint h, GLuint d) { struct st_texture_object *stObj = st_texture_object(stImage->base.TexObject); @@ -249,9 +250,9 @@ st_texture_image_map(struct st_context *st, struct st_texture_image *stImage, else level = stImage->base.Level; - return pipe_transfer_map(st->pipe, stImage->pt, level, - stImage->base.Face + zoffset, - usage, x, y, w, h, &stImage->transfer); + return pipe_transfer_map_3d(st->pipe, stImage->pt, level, usage, + x, y, z + stImage->base.Face, + w, h, d, &stImage->transfer); } diff --git a/mesalib/src/mesa/state_tracker/st_texture.h b/mesalib/src/mesa/state_tracker/st_texture.h index 62e975bb4..8a701009a 100644 --- a/mesalib/src/mesa/state_tracker/st_texture.h +++ b/mesalib/src/mesa/state_tracker/st_texture.h @@ -176,12 +176,10 @@ st_texture_match_image(const struct pipe_resource *pt, * well. */ extern GLubyte * -st_texture_image_map(struct st_context *st, - struct st_texture_image *stImage, - GLuint zoffset, +st_texture_image_map(struct st_context *st, struct st_texture_image *stImage, enum pipe_transfer_usage usage, - unsigned x, unsigned y, - unsigned w, unsigned h); + GLuint x, GLuint y, GLuint z, + GLuint w, GLuint h, GLuint d); extern void st_texture_image_unmap(struct st_context *st, diff --git a/mesalib/src/mesa/vbo/vbo.h b/mesalib/src/mesa/vbo/vbo.h index 04930b971..49dab2314 100644 --- a/mesalib/src/mesa/vbo/vbo.h +++ b/mesalib/src/mesa/vbo/vbo.h @@ -156,7 +156,8 @@ void vbo_check_buffers_are_unmapped(struct gl_context *ctx); void vbo_bind_arrays(struct gl_context *ctx); size_t -vbo_count_tessellated_primitives(const struct _mesa_prim *prim); +vbo_count_tessellated_primitives(GLenum mode, GLuint count, + GLuint num_instances); void vbo_sw_primitive_restart(struct gl_context *ctx, diff --git a/mesalib/src/mesa/vbo/vbo_exec.c b/mesalib/src/mesa/vbo/vbo_exec.c index 361d7a3e4..5827f90c3 100644 --- a/mesalib/src/mesa/vbo/vbo_exec.c +++ b/mesalib/src/mesa/vbo/vbo_exec.c @@ -94,47 +94,51 @@ void vbo_exec_invalidate_state( struct gl_context *ctx, GLuint new_state ) /** * Figure out the number of transform feedback primitives that will be output - * by the given _mesa_prim command, assuming that no geometry shading is done - * and primitive restart is not used. + * considering the drawing mode, number of vertices, and instance count, + * assuming that no geometry shading is done and primitive restart is not + * used. * - * This is intended for use by driver back-ends in implementing the - * PRIMITIVES_GENERATED and TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN queries. + * This is used by driver back-ends in implementing the PRIMITIVES_GENERATED + * and TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN queries. It is also used to + * pre-validate draw calls in GLES3 (where draw calls only succeed if there is + * enough room in the transform feedback buffer for the result). */ size_t -vbo_count_tessellated_primitives(const struct _mesa_prim *prim) +vbo_count_tessellated_primitives(GLenum mode, GLuint count, + GLuint num_instances) { size_t num_primitives; - switch (prim->mode) { + switch (mode) { case GL_POINTS: - num_primitives = prim->count; + num_primitives = count; break; case GL_LINE_STRIP: - num_primitives = prim->count >= 2 ? prim->count - 1 : 0; + num_primitives = count >= 2 ? count - 1 : 0; break; case GL_LINE_LOOP: - num_primitives = prim->count >= 2 ? prim->count : 0; + num_primitives = count >= 2 ? count : 0; break; case GL_LINES: - num_primitives = prim->count / 2; + num_primitives = count / 2; break; case GL_TRIANGLE_STRIP: case GL_TRIANGLE_FAN: case GL_POLYGON: - num_primitives = prim->count >= 3 ? prim->count - 2 : 0; + num_primitives = count >= 3 ? count - 2 : 0; break; case GL_TRIANGLES: - num_primitives = prim->count / 3; + num_primitives = count / 3; break; case GL_QUAD_STRIP: - num_primitives = prim->count >= 4 ? ((prim->count / 2) - 1) * 2 : 0; + num_primitives = count >= 4 ? ((count / 2) - 1) * 2 : 0; break; case GL_QUADS: - num_primitives = (prim->count / 4) * 2; + num_primitives = (count / 4) * 2; break; default: assert(!"Unexpected primitive type in count_tessellated_primitives"); num_primitives = 0; break; } - return num_primitives * prim->num_instances; + return num_primitives * num_instances; } |